mirror of
https://github.com/java-diff-utils/java-diff-utils.git
synced 2026-03-13 10:11:17 +08:00
Compare commits
208 Commits
diffutils-
...
java-diff-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76ae5f3b6f | ||
|
|
7d88486bdc | ||
|
|
694e93143d | ||
|
|
dac751bf73 | ||
|
|
f76abb58f6 | ||
|
|
de04bd688a | ||
|
|
e38cd3a99f | ||
|
|
96f7fbdebd | ||
|
|
d3524314eb | ||
|
|
85c3199570 | ||
|
|
dbe601c2fc | ||
|
|
fc7c714264 | ||
|
|
dcc29eee7e | ||
|
|
f0f5d241c7 | ||
|
|
e11c1599ee | ||
|
|
73c4c307a9 | ||
|
|
8006986dd8 | ||
|
|
f292c97dae | ||
|
|
7620f919c2 | ||
|
|
a8e4ce2eff | ||
|
|
9bd7aaa0f2 | ||
|
|
80c17a30d9 | ||
|
|
b5569703c8 | ||
|
|
47fe8e0ea6 | ||
|
|
ba4bd7ff03 | ||
|
|
ea8d442d28 | ||
|
|
fbb51d28c7 | ||
|
|
5781cc5178 | ||
|
|
37310e1628 | ||
|
|
ccfc40234a | ||
|
|
1e7d96e056 | ||
|
|
f0fc883485 | ||
|
|
3bc40a14f3 | ||
|
|
29de84cd96 | ||
|
|
11b3c53d2b | ||
|
|
d34591ed13 | ||
|
|
89c9f94aef | ||
|
|
9a39411ee8 | ||
|
|
ae23408748 | ||
|
|
923918a53e | ||
|
|
21d2cbbcdd | ||
|
|
fe6dbe243a | ||
|
|
df01ef67e3 | ||
|
|
dbd0b8f72e | ||
|
|
e37a52395a | ||
|
|
fb7fca643b | ||
|
|
94ffdab46f | ||
|
|
ca0959a0a1 | ||
|
|
3b23656260 | ||
|
|
39efdd5143 | ||
|
|
7dec3fef40 | ||
|
|
81085d368c | ||
|
|
15a5f060b3 | ||
|
|
93334b5da7 | ||
|
|
3c6fa5f4fe | ||
|
|
49b20133c2 | ||
|
|
84662956a0 | ||
|
|
f1b81c621b | ||
|
|
ededee0596 | ||
|
|
3b45d8f37d | ||
|
|
eada27b370 | ||
|
|
1d98467cc3 | ||
|
|
6c58e219b0 | ||
|
|
d5f7ffca5c | ||
|
|
f194a871b1 | ||
|
|
ab9908f3bc | ||
|
|
8c7bb30b25 | ||
|
|
6c617ff949 | ||
|
|
0d9f2ce62d | ||
|
|
ce4007b124 | ||
|
|
6e4e3910c1 | ||
|
|
23a9c523c6 | ||
|
|
53c9ca3478 | ||
|
|
7d17c6088a | ||
|
|
17eced9367 | ||
|
|
c534ebae98 | ||
|
|
156f4f2986 | ||
|
|
c5b88e02db | ||
|
|
f3ff104a9c | ||
|
|
a24ceb930d | ||
|
|
e82408e7a8 | ||
|
|
93a5255007 | ||
|
|
73263b41cf | ||
|
|
a46d44643f | ||
|
|
fb3a8427bc | ||
|
|
5ab1882df8 | ||
|
|
865a464906 | ||
|
|
bb79a9b4fe | ||
|
|
4a5a39cf96 | ||
|
|
a40c396678 | ||
|
|
a3663002bb | ||
|
|
69cb8c520d | ||
|
|
0c75b43d88 | ||
|
|
5cc9625275 | ||
|
|
e520ee2f20 | ||
|
|
de227395cd | ||
|
|
ddd66e4554 | ||
|
|
4700647351 | ||
|
|
4727557814 | ||
|
|
630eed340b | ||
|
|
a018e9c432 | ||
|
|
d30d9ca23a | ||
|
|
7d620c825c | ||
|
|
16cd9c6484 | ||
|
|
30875cf6db | ||
|
|
a34c185a44 | ||
|
|
a8d968cc1d | ||
|
|
89f2659dd7 | ||
|
|
9704b62970 | ||
|
|
ecd834f3f5 | ||
|
|
8c6679e295 | ||
|
|
4c1a0bc072 | ||
|
|
fd64d15ab0 | ||
|
|
13f2f5ede1 | ||
|
|
1c3a2b598e | ||
|
|
4719139448 | ||
|
|
b5eb632a4d | ||
|
|
6321d5327c | ||
|
|
a4bb85bab1 | ||
|
|
535ecf3e2a | ||
|
|
61a21cbca9 | ||
|
|
4a83032d7e | ||
|
|
8c86e0f8d7 | ||
|
|
983ec680f7 | ||
|
|
05b5d80d48 | ||
|
|
d2355a8435 | ||
|
|
55e4867e88 | ||
|
|
253a94becb | ||
|
|
a523ba3a14 | ||
|
|
361c27d5e7 | ||
|
|
c917f77bbf | ||
|
|
4caf63c193 | ||
|
|
c0a1a3777c | ||
|
|
2787a2db6c | ||
|
|
e8c015a2ec | ||
|
|
765dc29386 | ||
|
|
a312ec14ea | ||
|
|
3443d55a19 | ||
|
|
b41e2d5b5a | ||
|
|
47c6e9b417 | ||
|
|
2d116d8c54 | ||
|
|
de2f19497a | ||
|
|
5dd05c480d | ||
|
|
fc1e247de2 | ||
|
|
ab05a8bdb4 | ||
|
|
5fe7e58f76 | ||
|
|
785c368f01 | ||
|
|
c9a2c9e7f0 | ||
|
|
4bab820483 | ||
|
|
4fe80bdf1e | ||
|
|
005ba349f8 | ||
|
|
0fbbb53b77 | ||
|
|
d5fbf5022e | ||
|
|
2c85597238 | ||
|
|
f88ce15ff8 | ||
|
|
30a23c00d1 | ||
|
|
306f92684f | ||
|
|
d4f114226d | ||
|
|
65183197c5 | ||
|
|
5c33149e2a | ||
|
|
b273da278e | ||
|
|
2671949b92 | ||
|
|
5a32ede79f | ||
|
|
5dc489a4ef | ||
|
|
f2ab70afc4 | ||
|
|
c410422860 | ||
|
|
1161243bc2 | ||
|
|
f0fe7a2137 | ||
|
|
d506d62a91 | ||
|
|
33f2d744ab | ||
|
|
696d22bd94 | ||
|
|
42780b18a8 | ||
|
|
13a1522d46 | ||
|
|
d12b13da41 | ||
|
|
c8f0624a7b | ||
|
|
54bf402a9a | ||
|
|
3a87d24632 | ||
|
|
67b26e5cab | ||
|
|
592ff058c1 | ||
|
|
553ef27e0c | ||
|
|
d1c22e7243 | ||
|
|
0d15097947 | ||
|
|
dbfdffd626 | ||
|
|
33a0b58299 | ||
|
|
db114a2c2a | ||
|
|
c001819855 | ||
|
|
c6e4059de4 | ||
|
|
653d1f9153 | ||
|
|
1214f4cf23 | ||
|
|
04832c7c9a | ||
|
|
d498a41dd3 | ||
|
|
a998d8d98b | ||
|
|
91ddcccd1e | ||
|
|
005f95ab9d | ||
|
|
1914de7e5c | ||
|
|
e630c7975a | ||
|
|
10c17b4287 | ||
|
|
08d4914a8b | ||
|
|
df3ec97df4 | ||
|
|
8c242a42ef | ||
|
|
05de2df99d | ||
|
|
0eb7b6c34f | ||
|
|
5e0d398c53 | ||
|
|
829567bace | ||
|
|
02c97e4691 | ||
|
|
4933ca5200 | ||
|
|
a65ffd95a9 | ||
|
|
dcf66dfadc |
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: https://paypal.me/wumpz
|
||||
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Example data
|
||||
2. simple programm snippet
|
||||
3. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**System**
|
||||
- Java version
|
||||
- Version [e.g. 22]
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,2 +1,6 @@
|
||||
/target/
|
||||
/nbproject/
|
||||
.idea/
|
||||
build/
|
||||
nbproject/
|
||||
target/
|
||||
|
||||
*.iml
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- openjdk8
|
||||
- openjdk11
|
||||
|
||||
after_success:
|
||||
- mvn clean
|
||||
- mvn clean
|
||||
|
||||
110
CHANGELOG.md
Normal file
110
CHANGELOG.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
This project uses a custom versioning scheme (and not [Semantic Versioning](https://semver.org/spec/v2.0.0.html)).
|
||||
|
||||
## [unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
## [4.8]
|
||||
|
||||
### Changed
|
||||
|
||||
* some bugfixes regarding unified diff writer
|
||||
* UnifiedDiffReader improved for **deleted file mode** and better timestamp recognition
|
||||
* UnifiedDiffReader improved for **new file mode** and better timestamp recognition
|
||||
|
||||
## [4.7]
|
||||
|
||||
### Changed
|
||||
|
||||
* minor bug fixes
|
||||
* optional include equal parts of original and revised data
|
||||
* **API** change: removed DiffException completely
|
||||
* added possibility to **process diffs** to for instance show whitespace characters
|
||||
|
||||
## [4.4] – 2019-11-06
|
||||
|
||||
### Changed
|
||||
|
||||
* java-diff-utils is now a multi module project. The main project java-diff-utils now comes without any dependencies.
|
||||
* started reimplementation of unified diff tools
|
||||
* Exchange `0 += 1` for `0 = 1` in UnifiedDiffUtils
|
||||
* preview of new Unified Diff Reader / Writer. This is not yet feature complete but passes the tests of the old version.
|
||||
* feel free to issue some change requests for the api.
|
||||
* introduces lineNormalizer extension point to e.g. change html code encoding. (issue #41)
|
||||
|
||||
## [4.0] – 2019-01-09
|
||||
|
||||
### Changed
|
||||
|
||||
* moved to organisation **java-diff-utils**
|
||||
* changed groupid to **io.github.java-diff-utils** and artifact id to **java-diff-utils**
|
||||
|
||||
## [3.0] – 2018-10-18
|
||||
|
||||
### Added
|
||||
|
||||
* Introduced a process listener to diff algorithms. For long running
|
||||
diffs one could implement some progress information.
|
||||
* automatic module name for JDK 9 and higher usage
|
||||
|
||||
### Changed
|
||||
|
||||
* changed generation of inline diffes, if there are different linefeeds within one diff, then these are excluded from the diff block.
|
||||
|
||||
### Removed
|
||||
|
||||
* Due to licensing issues Delta.java and DiffAlgorithm.java were removed.
|
||||
|
||||
## [2.2] – 2017-11-09
|
||||
|
||||
### Added
|
||||
|
||||
* released at maven central
|
||||
* included checkstyle source code conventions
|
||||
* allow configurable splitting of lines to define the blocks to compare (words, characters, phrases).
|
||||
|
||||
### Changed
|
||||
|
||||
* groupid changed to **com.github.wumpz**, due to maven central releasing
|
||||
|
||||
## [2.0] – 2017-08-14
|
||||
|
||||
### Added
|
||||
|
||||
* support for inline merge
|
||||
* integrated JGit (Eclipse Licensed) to provide HistogramDiff to gain speed for large datasets
|
||||
|
||||
### Changed
|
||||
|
||||
* switch to maven and removed other artifacts
|
||||
* changed groupid to **com.github.java-diff-utils** due to different forks at github
|
||||
* updated maven plugins
|
||||
* JDK 1.8 compatibility, sorry if you have to stick with older versions
|
||||
* restructured packages heavily
|
||||
* changed API
|
||||
* changed Algorithm to provide only cursor positions
|
||||
|
||||
### Removed
|
||||
|
||||
* removed all kinds of helper classes in favour of new JDK 8 function classes like Predicate
|
||||
|
||||
## 1.2
|
||||
|
||||
### Added
|
||||
|
||||
* JDK 1.5 compatibility
|
||||
* Ant build script
|
||||
* Generate output in unified diff format (thanks for Bill James)
|
||||
|
||||
[Unreleased]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-parent-4.5...HEAD
|
||||
[4.5]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-parent-4.4...java-diff-utils-parent-4.5
|
||||
[4.4]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-4.0...java-diff-utils-parent-4.4
|
||||
[4.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diffutils-3.0...java-diff-utils-4.0
|
||||
[3.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diffutils-2.2...diffutils-3.0
|
||||
[2.2]: https://github.com/java-diff-utils/java-diff-utils/compare/diffutils-2.0...diffutils-2.2
|
||||
|
||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
100
README.md
100
README.md
@@ -1,18 +1,26 @@
|
||||
# java-diff-utils
|
||||
|
||||
## Status ##
|
||||
[](https://travis-ci.org/wumpz/java-diff-utils) [](https://www.codacy.com/app/wumpz/java-diff-utils?utm_source=github.com&utm_medium=referral&utm_content=wumpz/java-diff-utils&utm_campaign=Badge_Grade)
|
||||
## Status
|
||||
|
||||
[](https://travis-ci.org/java-diff-utils/java-diff-utils)
|
||||
[](https://www.codacy.com/app/wumpz/java-diff-utils?utm_source=github.com&utm_medium=referral&utm_content=java-diff-utils/java-diff-utils&utm_campaign=Badge_Grade)
|
||||
[](http://maven-badges.herokuapp.com/maven-central/io.github.java-diff-utils/java-diff-utils)
|
||||
|
||||
## Intro
|
||||
|
||||
## Intro ##
|
||||
Diff Utils library is an OpenSource library for performing the comparison operations between texts: computing diffs, applying patches, generating unified diffs or parsing them, generating diff output for easy future displaying (like side-by-side view) and so on.
|
||||
|
||||
Main reason to build this library was the lack of easy-to-use libraries with all the usual stuff you need while working with diff files. Originally it was inspired by JRCS library and it's nice design of diff module.
|
||||
|
||||
**This is originally a fork of java-diff-utils from Google Code Archive.**
|
||||
|
||||
## Examples ##
|
||||
## API
|
||||
|
||||
Look [here](https://github.com/wumpz/java-diff-utils/wiki) to find more helpful informations and examples.
|
||||
Javadocs of the actual release version: [JavaDocs java-diff-utils](https://java-diff-utils.github.io/java-diff-utils/4.7/docs/api/)
|
||||
|
||||
## Examples
|
||||
|
||||
Look [here](https://github.com/wumpz/java-diff-utils/wiki) to find more helpful informations and examples.
|
||||
|
||||
These two outputs are generated using this java-diff-utils. The source code can also be found at the *Examples* page:
|
||||
|
||||
@@ -20,7 +28,6 @@ These two outputs are generated using this java-diff-utils. The source code can
|
||||
|
||||
This is a test ~senctence~**for diffutils**.
|
||||
|
||||
|
||||
**Producing a side by side view of computed differences.**
|
||||
|
||||
|original|new|
|
||||
@@ -29,76 +36,61 @@ This is a test ~senctence~**for diffutils**.
|
||||
|This is the second line.|This is the second line.|
|
||||
|~And here is the finish.~||
|
||||
|
||||
## Main Features
|
||||
|
||||
## Main Features ##
|
||||
* computing the difference between two texts.
|
||||
* capable to hand more than plain ascii. Arrays or List of any type that implements hashCode() and equals() correctly can be subject to differencing using this library
|
||||
* patch and unpatch the text with the given patch
|
||||
* parsing the unified diff format
|
||||
* producing human-readable differences
|
||||
* inline difference construction
|
||||
* Algorithms:
|
||||
* Myer
|
||||
* HistogramDiff using JGit Library
|
||||
|
||||
* computing the difference between two texts.
|
||||
* capable to hand more than plain ascci. Arrays or List of any type that implements hashCode() and equals() correctly can be subject to differencing using this library
|
||||
* patch and unpatch the text with the given patch
|
||||
* parsing the unified diff format
|
||||
* producing human-readable differences
|
||||
* inline difference construction
|
||||
* Algorithms:
|
||||
* Myer
|
||||
* HistogramDiff using JGit Library
|
||||
|
||||
### Algoritms ###
|
||||
### Algorithms
|
||||
|
||||
* Myer's diff
|
||||
* HistogramDiff
|
||||
* HistogramDiff
|
||||
|
||||
But it can easily replaced by any other which is better for handing your texts. I have plan to add implementation of some in future.
|
||||
|
||||
### Changelog ###
|
||||
* Version 2.1-SNAPSHOT
|
||||
* included checkstyle source code conventions
|
||||
* groupid changed to **com.github.wumpz**, due to maven central releasing
|
||||
* allow configurable splitting of lines to define the blocks to compare (words, characters, phrases).
|
||||
* Version 2.0
|
||||
* switch to maven and removed other artifacts
|
||||
* changed groupid to **com.github.java-diff-utils** due to different forks at github
|
||||
* updated maven plugins
|
||||
* JDK 1.8 compatibility, sorry if you have to stick with older versions
|
||||
* support for inline merge
|
||||
* restructured packages heavily
|
||||
* changed API
|
||||
* changed Algorithm to provide only cursor positions
|
||||
* integrated JGit (Eclipse Licensed) to provide HistogramDiff to gain speed for large datasets
|
||||
* removed all kinds of helper classes in favour of new JDK 8 function classes like Predicate
|
||||
* Version 1.2
|
||||
* JDK 1.5 compatibility
|
||||
* Ant build script
|
||||
* Generate output in unified diff format (thanks for Bill James)
|
||||
|
||||
## Source Code conventions
|
||||
|
||||
Recently a checkstyle process was integrated into the build process. JSqlParser follows the sun java format convention. There are no TABs allowed. Use spaces.
|
||||
Recently a checkstyle process was integrated into the build process. java-diff-utils follows the sun java format convention. There are no TABs allowed. Use spaces.
|
||||
|
||||
```java
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
BiPredicate<T, T> equalizer) throws DiffException {
|
||||
if (equalizer != null) {
|
||||
return DiffUtils.diff(original, revised,
|
||||
new MyersDiff<>(equalizer));
|
||||
}
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>());
|
||||
BiPredicate<T, T> equalizer) throws DiffException {
|
||||
if (equalizer != null) {
|
||||
return DiffUtils.diff(original, revised,
|
||||
new MyersDiff<>(equalizer));
|
||||
}
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>());
|
||||
}
|
||||
```
|
||||
|
||||
This is a valid piece of source code:
|
||||
|
||||
* blocks without braces are not allowed
|
||||
* after control statements (if, while, for) a whitespace is expected
|
||||
* the opening brace should be in the same line as the control statement
|
||||
|
||||
### To Install ###
|
||||
|
||||
**This jar is not yet to get at maven central.**
|
||||
### To Install
|
||||
|
||||
Just add the code below to your maven dependencies:
|
||||
```
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.github.wumpz</groupId>
|
||||
<artifactId>diffutils</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
<version>4.5</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
or using gradle:
|
||||
|
||||
```groovy
|
||||
// https://mvnrepository.com/artifact/io.github.java-diff-utils/java-diff-utils
|
||||
implementation "io.github.java-diff-utils:java-diff-utils:4.5"
|
||||
```
|
||||
|
||||
18
java-diff-utils-jgit/nb-configuration.xml
Normal file
18
java-diff-utils-jgit/nb-configuration.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-shared-configuration>
|
||||
<!--
|
||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||
The configuration is intended to be shared among all the users of project and
|
||||
therefore it is assumed to be part of version control checkout.
|
||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||
-->
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||
-->
|
||||
<netbeans.compile.on.save>none</netbeans.compile.on.save>
|
||||
</properties>
|
||||
</project-shared-configuration>
|
||||
57
java-diff-utils-jgit/pom.xml
Normal file
57
java-diff-utils-jgit/pom.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.8</version>
|
||||
</parent>
|
||||
<artifactId>java-diff-utils-jgit</artifactId>
|
||||
<name>java-diff-utils-jgit</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>This is an extension of java-diff-utils using jgit to use its implementation of
|
||||
some difference algorithms.</description>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>5.8.1.202007141445-r</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.googlecode.javaewah</groupId>
|
||||
<artifactId>JavaEWAH</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -16,8 +16,8 @@
|
||||
package com.github.difflib.algorithm.jgit;
|
||||
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import com.github.difflib.algorithm.DiffAlgorithm;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -28,18 +28,22 @@ import org.eclipse.jgit.diff.Sequence;
|
||||
import org.eclipse.jgit.diff.SequenceComparator;
|
||||
|
||||
/**
|
||||
* HistorgramDiff using JGit - Library. This one is much more performant than the orginal Myers implementation.
|
||||
* HistorgramDiff using JGit - Library. This one is much more performant than the orginal Myers
|
||||
* implementation.
|
||||
*
|
||||
* @author toben
|
||||
*/
|
||||
public class HistogramDiff<T> implements DiffAlgorithm<T> {
|
||||
public class HistogramDiff<T> implements DiffAlgorithmI<T> {
|
||||
|
||||
@Override
|
||||
public List<Change> diff(List<T> original, List<T> revised) throws DiffException {
|
||||
Objects.requireNonNull(original, "original list must not be null");
|
||||
Objects.requireNonNull(revised, "revised list must not be null");
|
||||
public List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) {
|
||||
Objects.requireNonNull(source, "source list must not be null");
|
||||
Objects.requireNonNull(target, "target list must not be null");
|
||||
if (progress != null) {
|
||||
progress.diffStart();
|
||||
}
|
||||
EditList diffList = new EditList();
|
||||
diffList.addAll(new org.eclipse.jgit.diff.HistogramDiff().diff(new DataListComparator<>(), new DataList<>(original), new DataList<>(revised)));
|
||||
diffList.addAll(new org.eclipse.jgit.diff.HistogramDiff().diff(new DataListComparator<>(progress), new DataList<>(source), new DataList<>(target)));
|
||||
List<Change> patch = new ArrayList<>();
|
||||
for (Edit edit : diffList) {
|
||||
DeltaType type = DeltaType.EQUAL;
|
||||
@@ -56,14 +60,26 @@ public class HistogramDiff<T> implements DiffAlgorithm<T> {
|
||||
}
|
||||
patch.add(new Change(type, edit.getBeginA(), edit.getEndA(), edit.getBeginB(), edit.getEndB()));
|
||||
}
|
||||
if (progress != null) {
|
||||
progress.diffEnd();
|
||||
}
|
||||
return patch;
|
||||
}
|
||||
}
|
||||
|
||||
class DataListComparator<T> extends SequenceComparator<DataList<T>> {
|
||||
|
||||
private final DiffAlgorithmListener progress;
|
||||
|
||||
public DataListComparator(DiffAlgorithmListener progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(DataList<T> original, int orgIdx, DataList<T> revised, int revIdx) {
|
||||
if (progress != null) {
|
||||
progress.diffStep(orgIdx + revIdx, original.size() + revised.size());
|
||||
}
|
||||
return original.data.get(orgIdx).equals(revised.data.get(revIdx));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.jgit;
|
||||
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author toben
|
||||
*/
|
||||
public class HistogramDiffTest {
|
||||
|
||||
public HistogramDiffTest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of diff method, of class HistogramDiff.
|
||||
*/
|
||||
@Test
|
||||
public void testDiff() throws PatchFailedException {
|
||||
List<String> orgList = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revList = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(orgList, revList, new HistogramDiff().computeDiff(orgList, revList, null));
|
||||
System.out.println(patch);
|
||||
assertNotNull(patch);
|
||||
assertEquals(3, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [DeleteDelta, position: 3, lines: [A, B]], [InsertDelta, position: 7, lines: [B, A, C]]]}", patch.toString());
|
||||
|
||||
List<String> patched = patch.applyTo(orgList);
|
||||
assertEquals(revList, patched);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffWithListener() throws PatchFailedException {
|
||||
List<String> orgList = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revList = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
|
||||
List<String> logdata = new ArrayList<>();
|
||||
final Patch<String> patch = Patch.generate(orgList, revList, new HistogramDiff().computeDiff(orgList, revList, new DiffAlgorithmListener() {
|
||||
@Override
|
||||
public void diffStart() {
|
||||
logdata.add("start");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffStep(int value, int max) {
|
||||
logdata.add(value + " - " + max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffEnd() {
|
||||
logdata.add("end");
|
||||
}
|
||||
}));
|
||||
System.out.println(patch);
|
||||
assertNotNull(patch);
|
||||
assertEquals(3, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [DeleteDelta, position: 3, lines: [A, B]], [InsertDelta, position: 7, lines: [B, A, C]]]}", patch.toString());
|
||||
|
||||
List<String> patched = patch.applyTo(orgList);
|
||||
assertEquals(revList, patched);
|
||||
|
||||
System.out.println(logdata);
|
||||
assertEquals(19, logdata.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.jgit;
|
||||
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import java.util.zip.ZipFile;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author toben
|
||||
*/
|
||||
public class LRHistogramDiffTest {
|
||||
|
||||
@Test
|
||||
public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException, PatchFailedException {
|
||||
ZipFile zip = new ZipFile("target/test-classes/mocks/large_dataset1.zip");
|
||||
List<String> original = readStringListFromInputStream(zip.getInputStream(zip.getEntry("ta")));
|
||||
List<String> revised = readStringListFromInputStream(zip.getInputStream(zip.getEntry("tb")));
|
||||
|
||||
List<String> logdata = new ArrayList<>();
|
||||
Patch<String> patch = Patch.generate(original, revised, new HistogramDiff().computeDiff(original, revised, new DiffAlgorithmListener() {
|
||||
@Override
|
||||
public void diffStart() {
|
||||
logdata.add("start");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffStep(int value, int max) {
|
||||
logdata.add(value + " - " + max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffEnd() {
|
||||
logdata.add("end");
|
||||
}
|
||||
}));
|
||||
|
||||
assertEquals(34, patch.getDeltas().size());
|
||||
|
||||
List<String> created = patch.applyTo(original);
|
||||
assertArrayEquals(revised.toArray(), created.toArray());
|
||||
|
||||
assertEquals(246579, logdata.size());
|
||||
}
|
||||
|
||||
public static List<String> readStringListFromInputStream(InputStream is) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(is, Charset.forName(StandardCharsets.UTF_8.name())))) {
|
||||
|
||||
return reader.lines().collect(toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
19
java-diff-utils/nb-configuration.xml
Normal file
19
java-diff-utils/nb-configuration.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-shared-configuration>
|
||||
<!--
|
||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||
The configuration is intended to be shared among all the users of project and
|
||||
therefore it is assumed to be part of version control checkout.
|
||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||
-->
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||
-->
|
||||
<netbeans.hint.jdkPlatform>JDK_1.8</netbeans.hint.jdkPlatform>
|
||||
<netbeans.compile.on.save>none</netbeans.compile.on.save>
|
||||
</properties>
|
||||
</project-shared-configuration>
|
||||
67
java-diff-utils/pom.xml
Normal file
67
java-diff-utils/pom.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>java-diff-utils</name>
|
||||
<parent>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.8</version>
|
||||
</parent>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
<manifestEntries>
|
||||
<!-- identical to OSGI name -->
|
||||
<Automatic-Module-Name>io.github.javadiffutils</Automatic-Module-Name>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.config.file>target/test-classes/logging.properties</java.util.logging.config.file>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib;
|
||||
|
||||
import com.github.difflib.algorithm.DiffAlgorithm;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.algorithm.myers.MyersDiff;
|
||||
import com.github.difflib.patch.Delta;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.util.ArrayList;
|
||||
@@ -31,79 +27,117 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/**
|
||||
* Implements the difference and patching engine
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @version 0.4.1
|
||||
*/
|
||||
public final class DiffUtils {
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff algorithm
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
*
|
||||
* @param <T> types to be diffed
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never {@code null}.
|
||||
* @param progress progress listener
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised) throws DiffException {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>());
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), progress);
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), null);
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), null, includeEqualParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised text.
|
||||
*/
|
||||
public static Patch<String> diff(String originalText, String revisedText) throws DiffException {
|
||||
return DiffUtils.diff(Arrays.asList(originalText.split("\n")), Arrays.asList(revisedText.split("\n")));
|
||||
public static Patch<String> diff(String sourceText, String targetText,
|
||||
DiffAlgorithmListener progress) {
|
||||
return DiffUtils.diff(
|
||||
Arrays.asList(sourceText.split("\n")),
|
||||
Arrays.asList(targetText.split("\n")), progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff algorithm
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
*
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param source The original text. Must not be {@code null}.
|
||||
* @param target The revised text. Must not be {@code null}.
|
||||
*
|
||||
* @param equalizer the equalizer object to replace the default compare algorithm (Object.equals). If {@code null}
|
||||
* the default equalizer of the default algorithm is used..
|
||||
* @return The patch describing the difference between the original and revised sequences. Never {@code null}.
|
||||
* @param equalizer the equalizer object to replace the default compare algorithm
|
||||
* (Object.equals). If {@code null} the default equalizer of the default algorithm is used..
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
BiPredicate<T, T> equalizer) throws DiffException {
|
||||
public static <T> Patch<T> diff(List<T> source, List<T> target,
|
||||
BiPredicate<T, T> equalizer) {
|
||||
if (equalizer != null) {
|
||||
return DiffUtils.diff(original, revised,
|
||||
return DiffUtils.diff(source, target,
|
||||
new MyersDiff<>(equalizer));
|
||||
}
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>());
|
||||
return DiffUtils.diff(source, target, new MyersDiff<>());
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) {
|
||||
return diff(original, revised, algorithm, progress, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff algorithm
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
*
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param algorithm The diff algorithm. Must not be {@code null}.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never {@code null}.
|
||||
* @param progress The diff algorithm listener.
|
||||
* @param includeEqualParts Include equal data parts into the patch.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
DiffAlgorithm<T> algorithm) throws DiffException {
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress,
|
||||
boolean includeEqualParts) {
|
||||
Objects.requireNonNull(original, "original must not be null");
|
||||
Objects.requireNonNull(revised, "revised must not be null");
|
||||
Objects.requireNonNull(algorithm, "algorithm must not be null");
|
||||
|
||||
return Patch.generate(original, revised, algorithm.diff(original, revised));
|
||||
return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress), includeEqualParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the given texts inline. This one uses the "trick" to make out of texts lists of
|
||||
* characters, like DiffRowGenerator does and merges those changes at the end together again.
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
*
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param algorithm The diff algorithm. Must not be {@code null}.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmI<T> algorithm) {
|
||||
return diff(original, revised, algorithm, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the given texts inline. This one uses the "trick" to make out
|
||||
* of texts lists of characters, like DiffRowGenerator does and merges those changes at the end
|
||||
* together again.
|
||||
*
|
||||
* @param original
|
||||
* @param revised
|
||||
* @return
|
||||
*/
|
||||
public static Patch<String> diffInline(String original, String revised) throws DiffException {
|
||||
public static Patch<String> diffInline(String original, String revised) {
|
||||
List<String> origList = new ArrayList<>();
|
||||
List<String> revList = new ArrayList<>();
|
||||
for (Character character : original.toCharArray()) {
|
||||
@@ -113,9 +147,9 @@ public final class DiffUtils {
|
||||
revList.add(character.toString());
|
||||
}
|
||||
Patch<String> patch = DiffUtils.diff(origList, revList);
|
||||
for (Delta<String> delta : patch.getDeltas()) {
|
||||
delta.getOriginal().setLines(compressLines(delta.getOriginal().getLines(), ""));
|
||||
delta.getRevised().setLines(compressLines(delta.getRevised().getLines(), ""));
|
||||
for (AbstractDelta<String> delta : patch.getDeltas()) {
|
||||
delta.getSource().setLines(compressLines(delta.getSource().getLines(), ""));
|
||||
delta.getTarget().setLines(compressLines(delta.getTarget().getLines(), ""));
|
||||
}
|
||||
return patch;
|
||||
}
|
||||
@@ -124,7 +158,7 @@ public final class DiffUtils {
|
||||
if (lines.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(lines.stream().collect(joining(delimiter)));
|
||||
return Collections.singletonList(String.join(delimiter, lines));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -17,10 +17,11 @@ package com.github.difflib;
|
||||
|
||||
import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.Delta;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -32,6 +33,7 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
private static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern
|
||||
.compile("^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@$");
|
||||
private static final String NULL_FILE_INDICATOR = "/dev/null";
|
||||
|
||||
/**
|
||||
* Parse the given text in unified format and creates the list of deltas for it.
|
||||
@@ -59,34 +61,16 @@ public final class UnifiedDiffUtils {
|
||||
Matcher m = UNIFIED_DIFF_CHUNK_REGEXP.matcher(line);
|
||||
if (m.find()) {
|
||||
// Process the lines in the previous chunk
|
||||
if (!rawChunk.isEmpty()) {
|
||||
List<String> oldChunkLines = new ArrayList<>();
|
||||
List<String> newChunkLines = new ArrayList<>();
|
||||
|
||||
for (String[] raw_line : rawChunk) {
|
||||
tag = raw_line[0];
|
||||
rest = raw_line[1];
|
||||
if (" ".equals(tag) || "-".equals(tag)) {
|
||||
oldChunkLines.add(rest);
|
||||
}
|
||||
if (" ".equals(tag) || "+".equals(tag)) {
|
||||
newChunkLines.add(rest);
|
||||
}
|
||||
}
|
||||
patch.addDelta(new ChangeDelta<>(new Chunk<>(
|
||||
old_ln - 1, oldChunkLines), new Chunk<>(
|
||||
new_ln - 1, newChunkLines)));
|
||||
rawChunk.clear();
|
||||
}
|
||||
processLinesInPrevChunk(rawChunk, patch, old_ln, new_ln);
|
||||
// Parse the @@ header
|
||||
old_ln = m.group(1) == null ? 1 : Integer.parseInt(m.group(1));
|
||||
new_ln = m.group(3) == null ? 1 : Integer.parseInt(m.group(3));
|
||||
|
||||
if (old_ln == 0) {
|
||||
old_ln += 1;
|
||||
old_ln = 1;
|
||||
}
|
||||
if (new_ln == 0) {
|
||||
new_ln += 1;
|
||||
new_ln = 1;
|
||||
}
|
||||
} else {
|
||||
if (line.length() > 0) {
|
||||
@@ -102,65 +86,82 @@ public final class UnifiedDiffUtils {
|
||||
}
|
||||
|
||||
// Process the lines in the last chunk
|
||||
if (!rawChunk.isEmpty()) {
|
||||
List<String> oldChunkLines = new ArrayList<>();
|
||||
List<String> newChunkLines = new ArrayList<>();
|
||||
|
||||
for (String[] raw_line : rawChunk) {
|
||||
tag = raw_line[0];
|
||||
rest = raw_line[1];
|
||||
if (" ".equals(tag) || "-".equals(tag)) {
|
||||
oldChunkLines.add(rest);
|
||||
}
|
||||
if (" ".equals(tag) || "+".equals(tag)) {
|
||||
newChunkLines.add(rest);
|
||||
}
|
||||
}
|
||||
|
||||
patch.addDelta(new ChangeDelta<>(new Chunk<>(
|
||||
old_ln - 1, oldChunkLines), new Chunk<>(new_ln - 1,
|
||||
newChunkLines)));
|
||||
rawChunk.clear();
|
||||
}
|
||||
processLinesInPrevChunk(rawChunk, patch, old_ln, new_ln);
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
||||
private static void processLinesInPrevChunk(List<String[]> rawChunk, Patch<String> patch, int old_ln, int new_ln) {
|
||||
String tag;
|
||||
String rest;
|
||||
if (!rawChunk.isEmpty()) {
|
||||
List<String> oldChunkLines = new ArrayList<>();
|
||||
List<String> newChunkLines = new ArrayList<>();
|
||||
|
||||
List<Integer> removePosition = new ArrayList<>();
|
||||
List<Integer> addPosition = new ArrayList<>();
|
||||
int removeNum = 0;
|
||||
int addNum = 0;
|
||||
for (String[] raw_line : rawChunk) {
|
||||
tag = raw_line[0];
|
||||
rest = raw_line[1];
|
||||
if (" ".equals(tag) || "-".equals(tag)) {
|
||||
removeNum++;
|
||||
oldChunkLines.add(rest);
|
||||
if ("-".equals(tag)) {
|
||||
removePosition.add(old_ln - 1 + removeNum);
|
||||
}
|
||||
}
|
||||
if (" ".equals(tag) || "+".equals(tag)) {
|
||||
addNum++;
|
||||
newChunkLines.add(rest);
|
||||
if ("+".equals(tag)) {
|
||||
addPosition.add(new_ln - 1 + addNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
patch.addDelta(new ChangeDelta<>(new Chunk<>(
|
||||
old_ln - 1, oldChunkLines, removePosition), new Chunk<>(
|
||||
new_ln - 1, newChunkLines, addPosition)));
|
||||
rawChunk.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format text representing
|
||||
* the Patch.
|
||||
* generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format
|
||||
* text representing the Patch.
|
||||
*
|
||||
* @param original - Filename of the original (unrevised file)
|
||||
* @param revised - Filename of the revised file
|
||||
* @param originalFileName - Filename of the original (unrevised file)
|
||||
* @param revisedFileName - Filename of the revised file
|
||||
* @param originalLines - Lines of the original file
|
||||
* @param patch - Patch created by the diff() function
|
||||
* @param contextSize - number of lines of context output around each difference in the file.
|
||||
* @return List of strings representing the Unified Diff representation of the Patch argument.
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
public static List<String> generateUnifiedDiff(String original,
|
||||
String revised, List<String> originalLines, Patch<String> patch,
|
||||
public static List<String> generateUnifiedDiff(String originalFileName,
|
||||
String revisedFileName, List<String> originalLines, Patch<String> patch,
|
||||
int contextSize) {
|
||||
if (!patch.getDeltas().isEmpty()) {
|
||||
List<String> ret = new ArrayList<>();
|
||||
ret.add("--- " + original);
|
||||
ret.add("+++ " + revised);
|
||||
ret.add("--- " + Optional.ofNullable(originalFileName).orElse(NULL_FILE_INDICATOR));
|
||||
ret.add("+++ " + Optional.ofNullable(revisedFileName).orElse(NULL_FILE_INDICATOR));
|
||||
|
||||
List<Delta<String>> patchDeltas = new ArrayList<>(
|
||||
List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
|
||||
patch.getDeltas());
|
||||
|
||||
// code outside the if block also works for single-delta issues.
|
||||
List<Delta<String>> deltas = new ArrayList<>(); // current
|
||||
List<AbstractDelta<String>> deltas = new ArrayList<>(); // current
|
||||
// list
|
||||
// of
|
||||
// Delta's to
|
||||
// process
|
||||
Delta<String> delta = patchDeltas.get(0);
|
||||
AbstractDelta<String> delta = patchDeltas.get(0);
|
||||
deltas.add(delta); // add the first Delta to the current set
|
||||
// if there's more than 1 Delta, we may need to output them together
|
||||
if (patchDeltas.size() > 1) {
|
||||
for (int i = 1; i < patchDeltas.size(); i++) {
|
||||
int position = delta.getOriginal().getPosition(); // store
|
||||
int position = delta.getSource().getPosition(); // store
|
||||
// the
|
||||
// current
|
||||
// position
|
||||
@@ -170,16 +171,16 @@ public final class UnifiedDiffUtils {
|
||||
// Check if the next Delta is too close to the current
|
||||
// position.
|
||||
// And if it is, add it to the current set
|
||||
Delta<String> nextDelta = patchDeltas.get(i);
|
||||
if ((position + delta.getOriginal().size() + contextSize) >= (nextDelta
|
||||
.getOriginal().getPosition() - contextSize)) {
|
||||
AbstractDelta<String> nextDelta = patchDeltas.get(i);
|
||||
if ((position + delta.getSource().size() + contextSize) >= (nextDelta
|
||||
.getSource().getPosition() - contextSize)) {
|
||||
deltas.add(nextDelta);
|
||||
} else {
|
||||
// if it isn't, output the current set,
|
||||
// then create a new set and add the current Delta to
|
||||
// it.
|
||||
List<String> curBlock = processDeltas(originalLines,
|
||||
deltas, contextSize);
|
||||
deltas, contextSize, false);
|
||||
ret.addAll(curBlock);
|
||||
deltas.clear();
|
||||
deltas.add(nextDelta);
|
||||
@@ -190,7 +191,7 @@ public final class UnifiedDiffUtils {
|
||||
}
|
||||
// don't forget to process the last set of Deltas
|
||||
List<String> curBlock = processDeltas(originalLines, deltas,
|
||||
contextSize);
|
||||
contextSize, patchDeltas.size() == 1 && originalFileName == null);
|
||||
ret.addAll(curBlock);
|
||||
return ret;
|
||||
}
|
||||
@@ -198,7 +199,8 @@ public final class UnifiedDiffUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* processDeltas takes a list of Deltas and outputs them together in a single block of Unified-Diff-format text.
|
||||
* processDeltas takes a list of Deltas and outputs them together in a single block of
|
||||
* Unified-Diff-format text.
|
||||
*
|
||||
* @param origLines - the lines of the original file
|
||||
* @param deltas - the Deltas to be output as a single block
|
||||
@@ -207,33 +209,37 @@ public final class UnifiedDiffUtils {
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static List<String> processDeltas(List<String> origLines,
|
||||
List<Delta<String>> deltas, int contextSize) {
|
||||
List<AbstractDelta<String>> deltas, int contextSize, boolean newFile) {
|
||||
List<String> buffer = new ArrayList<>();
|
||||
int origTotal = 0; // counter for total lines output from Original
|
||||
int revTotal = 0; // counter for total lines output from Original
|
||||
int line;
|
||||
|
||||
Delta<String> curDelta = deltas.get(0);
|
||||
|
||||
// NOTE: +1 to overcome the 0-offset Position
|
||||
int origStart = curDelta.getOriginal().getPosition() + 1 - contextSize;
|
||||
if (origStart < 1) {
|
||||
origStart = 1;
|
||||
AbstractDelta<String> curDelta = deltas.get(0);
|
||||
int origStart;
|
||||
if (newFile) {
|
||||
origStart = 0;
|
||||
} else {
|
||||
// NOTE: +1 to overcome the 0-offset Position
|
||||
origStart = curDelta.getSource().getPosition() + 1 - contextSize;
|
||||
if (origStart < 1) {
|
||||
origStart = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int revStart = curDelta.getRevised().getPosition() + 1 - contextSize;
|
||||
int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
|
||||
if (revStart < 1) {
|
||||
revStart = 1;
|
||||
}
|
||||
|
||||
// find the start of the wrapper context code
|
||||
int contextStart = curDelta.getOriginal().getPosition() - contextSize;
|
||||
int contextStart = curDelta.getSource().getPosition() - contextSize;
|
||||
if (contextStart < 0) {
|
||||
contextStart = 0; // clamp to the start of the file
|
||||
}
|
||||
|
||||
// output the context before the first Delta
|
||||
for (line = contextStart; line < curDelta.getOriginal().getPosition(); line++) { //
|
||||
for (line = contextStart; line < curDelta.getSource().getPosition(); line++) { //
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
@@ -241,15 +247,15 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
// output the first Delta
|
||||
buffer.addAll(getDeltaText(curDelta));
|
||||
origTotal += curDelta.getOriginal().getLines().size();
|
||||
revTotal += curDelta.getRevised().getLines().size();
|
||||
origTotal += curDelta.getSource().getLines().size();
|
||||
revTotal += curDelta.getTarget().getLines().size();
|
||||
|
||||
int deltaIndex = 1;
|
||||
while (deltaIndex < deltas.size()) { // for each of the other Deltas
|
||||
Delta<String> nextDelta = deltas.get(deltaIndex);
|
||||
int intermediateStart = curDelta.getOriginal().getPosition()
|
||||
+ curDelta.getOriginal().getLines().size();
|
||||
for (line = intermediateStart; line < nextDelta.getOriginal()
|
||||
AbstractDelta<String> nextDelta = deltas.get(deltaIndex);
|
||||
int intermediateStart = curDelta.getSource().getPosition()
|
||||
+ curDelta.getSource().getLines().size();
|
||||
for (line = intermediateStart; line < nextDelta.getSource()
|
||||
.getPosition(); line++) {
|
||||
// output the code between the last Delta and this one
|
||||
buffer.add(" " + origLines.get(line));
|
||||
@@ -257,15 +263,15 @@ public final class UnifiedDiffUtils {
|
||||
revTotal++;
|
||||
}
|
||||
buffer.addAll(getDeltaText(nextDelta)); // output the Delta
|
||||
origTotal += nextDelta.getOriginal().getLines().size();
|
||||
revTotal += nextDelta.getRevised().getLines().size();
|
||||
origTotal += nextDelta.getSource().getLines().size();
|
||||
revTotal += nextDelta.getTarget().getLines().size();
|
||||
curDelta = nextDelta;
|
||||
deltaIndex++;
|
||||
}
|
||||
|
||||
// Now output the post-Delta context code, clamping the end of the file
|
||||
contextStart = curDelta.getOriginal().getPosition()
|
||||
+ curDelta.getOriginal().getLines().size();
|
||||
contextStart = curDelta.getSource().getPosition()
|
||||
+ curDelta.getSource().getLines().size();
|
||||
for (line = contextStart; (line < (contextStart + contextSize))
|
||||
&& (line < origLines.size()); line++) {
|
||||
buffer.add(" " + origLines.get(line));
|
||||
@@ -275,7 +281,7 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
// Create and insert the block header, conforming to the Unified Diff
|
||||
// standard
|
||||
StringBuffer header = new StringBuffer();
|
||||
StringBuilder header = new StringBuilder();
|
||||
header.append("@@ -");
|
||||
header.append(origStart);
|
||||
header.append(",");
|
||||
@@ -297,12 +303,12 @@ public final class UnifiedDiffUtils {
|
||||
* @return list of String lines of code.
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static List<String> getDeltaText(Delta<String> delta) {
|
||||
private static List<String> getDeltaText(AbstractDelta<String> delta) {
|
||||
List<String> buffer = new ArrayList<>();
|
||||
for (String line : delta.getOriginal().getLines()) {
|
||||
for (String line : delta.getSource().getLines()) {
|
||||
buffer.add("-" + line);
|
||||
}
|
||||
for (String line : delta.getRevised().getLines()) {
|
||||
for (String line : delta.getTarget().getLines()) {
|
||||
buffer.add("+" + line);
|
||||
}
|
||||
return buffer;
|
||||
@@ -19,7 +19,7 @@ import com.github.difflib.patch.DeltaType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author toben
|
||||
* @author <a href="t.warneke@gmx.net">Tobias Warneke</a>
|
||||
*/
|
||||
public class Change {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2018 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface of a diff algorithm.
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
* @param <T> type of data that is diffed.
|
||||
*/
|
||||
public interface DiffAlgorithmI<T> {
|
||||
|
||||
/**
|
||||
* Computes the changeset to patch the source list to the target list.
|
||||
*
|
||||
* @param source source data
|
||||
* @param target target data
|
||||
* @param progress progress listener
|
||||
* @return
|
||||
*/
|
||||
List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress);
|
||||
|
||||
/**
|
||||
* Simple extension to compute a changeset using arrays.
|
||||
*
|
||||
* @param source
|
||||
* @param target
|
||||
* @param progress
|
||||
* @return
|
||||
*/
|
||||
default List<Change> computeDiff(T[] source, T[] target, DiffAlgorithmListener progress) {
|
||||
return computeDiff(Arrays.asList(source), Arrays.asList(target), progress);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2018 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public interface DiffAlgorithmListener {
|
||||
void diffStart();
|
||||
|
||||
/**
|
||||
* This is a step within the diff algorithm. Due to different implementations the value
|
||||
* is not strict incrementing to the max and is not garantee to reach the max. It could
|
||||
* stop before.
|
||||
* @param value
|
||||
* @param max
|
||||
*/
|
||||
void diffStep(int value, int max);
|
||||
void diffEnd();
|
||||
}
|
||||
@@ -1,28 +1,23 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import com.github.difflib.algorithm.DiffAlgorithm;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.algorithm.DifferentiationFailedException;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.ArrayList;
|
||||
@@ -33,7 +28,7 @@ import java.util.function.BiPredicate;
|
||||
/**
|
||||
* A clean-room implementation of Eugene Myers greedy differencing algorithm.
|
||||
*/
|
||||
public final class MyersDiff<T> implements DiffAlgorithm<T> {
|
||||
public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
|
||||
private final BiPredicate<T, T> DEFAULT_EQUALIZER = Object::equals;
|
||||
private final BiPredicate<T, T> equalizer;
|
||||
@@ -53,25 +48,31 @@ public final class MyersDiff<T> implements DiffAlgorithm<T> {
|
||||
* Return empty diff if get the error while procession the difference.
|
||||
*/
|
||||
@Override
|
||||
public List<Change> diff(final List<T> original, final List<T> revised) throws DiffException {
|
||||
Objects.requireNonNull(original, "original list must not be null");
|
||||
Objects.requireNonNull(revised, "revised list must not be null");
|
||||
public List<Change> computeDiff(final List<T> source, final List<T> target, DiffAlgorithmListener progress) {
|
||||
Objects.requireNonNull(source, "source list must not be null");
|
||||
Objects.requireNonNull(target, "target list must not be null");
|
||||
|
||||
PathNode path = buildPath(original, revised);
|
||||
return buildRevision(path, original, revised);
|
||||
if (progress != null) {
|
||||
progress.diffStart();
|
||||
}
|
||||
PathNode path = buildPath(source, target, progress);
|
||||
List<Change> result = buildRevision(path, source, target);
|
||||
if (progress != null) {
|
||||
progress.diffEnd();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the minimum diffpath that expresses de differences between the original and revised sequences, according
|
||||
* to Gene Myers differencing algorithm.
|
||||
* Computes the minimum diffpath that expresses de differences between the original and revised
|
||||
* sequences, according to Gene Myers differencing algorithm.
|
||||
*
|
||||
* @param orig The original sequence.
|
||||
* @param rev The revised sequence.
|
||||
* @return A minimum {@link PathNode Path} accross the differences graph.
|
||||
* @throws DifferentiationFailedException if a diff path could not be found.
|
||||
*/
|
||||
private PathNode buildPath(final List<T> orig, final List<T> rev)
|
||||
throws DifferentiationFailedException {
|
||||
private PathNode buildPath(final List<T> orig, final List<T> rev, DiffAlgorithmListener progress) {
|
||||
Objects.requireNonNull(orig, "original sequence is null");
|
||||
Objects.requireNonNull(rev, "revised sequence is null");
|
||||
|
||||
@@ -86,6 +87,9 @@ public final class MyersDiff<T> implements DiffAlgorithm<T> {
|
||||
|
||||
diagonal[middle + 1] = new PathNode(0, -1, true, true, null);
|
||||
for (int d = 0; d < MAX; d++) {
|
||||
if (progress != null) {
|
||||
progress.diffStep(d, MAX);
|
||||
}
|
||||
for (int k = -d; k <= d; k += 2) {
|
||||
final int kmiddle = middle + k;
|
||||
final int kplus = kmiddle + 1;
|
||||
@@ -125,17 +129,18 @@ public final class MyersDiff<T> implements DiffAlgorithm<T> {
|
||||
diagonal[middle + d - 1] = null;
|
||||
}
|
||||
// According to Myers, this cannot happen
|
||||
throw new DifferentiationFailedException("could not find a diff path");
|
||||
throw new IllegalStateException("could not find a diff path");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link Patch} from a difference path.
|
||||
*
|
||||
* @param path The path.
|
||||
* @param actualPath The path.
|
||||
* @param orig The original sequence.
|
||||
* @param rev The revised sequence.
|
||||
* @return A {@link Patch} script corresponding to the path.
|
||||
* @throws DifferentiationFailedException if a {@link Patch} could not be built from the given path.
|
||||
* @throws DifferentiationFailedException if a {@link Patch} could not be built from the given
|
||||
* path.
|
||||
*/
|
||||
private List<Change> buildRevision(PathNode actualPath, List<T> orig, List<T> rev) {
|
||||
Objects.requireNonNull(actualPath, "path is null");
|
||||
@@ -165,18 +170,7 @@ public final class MyersDiff<T> implements DiffAlgorithm<T> {
|
||||
} else {
|
||||
changes.add(new Change(DeltaType.CHANGE, ianchor, i, janchor, j));
|
||||
}
|
||||
// Chunk<T> original = new Chunk<>(ianchor, copyOfRange(orig, ianchor, i));
|
||||
// Chunk<T> revised = new Chunk<>(janchor, copyOfRange(rev, janchor, j));
|
||||
// Delta<T> delta = null;
|
||||
// if (original.size() == 0 && revised.size() != 0) {
|
||||
// delta = new InsertDelta<>(original, revised);
|
||||
// } else if (original.size() > 0 && revised.size() == 0) {
|
||||
// delta = new DeleteDelta<>(original, revised);
|
||||
// } else {
|
||||
// delta = new ChangeDelta<>(original, revised);
|
||||
// }
|
||||
//
|
||||
// patch.addDelta(delta);
|
||||
|
||||
if (path.isSnake()) {
|
||||
path = path.prev;
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
@@ -23,10 +19,6 @@ package com.github.difflib.algorithm.myers;
|
||||
* A node in a diffpath.
|
||||
*
|
||||
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
|
||||
*
|
||||
* @see DiffNode
|
||||
* @see Snake
|
||||
*
|
||||
*/
|
||||
public final class PathNode {
|
||||
|
||||
@@ -82,10 +74,10 @@ public final class PathNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips sequences of {@link DiffNode DiffNodes} until a {@link Snake} or bootstrap node is found, or the end of the
|
||||
* Skips sequences of {@link PathNode PathNodes} until a snake or bootstrap node is found, or the end of the
|
||||
* path is reached.
|
||||
*
|
||||
* @return The next first {@link Snake} or bootstrap node in the path, or <code>null</code> if none found.
|
||||
* @return The next first {@link PathNode} or bootstrap node in the path, or <code>null</code> if none found.
|
||||
*/
|
||||
public final PathNode previousSnake() {
|
||||
if (isBootstrap()) {
|
||||
@@ -106,9 +98,9 @@ public final class PathNode {
|
||||
PathNode node = this;
|
||||
while (node != null) {
|
||||
buf.append("(");
|
||||
buf.append(Integer.toString(node.i));
|
||||
buf.append(node.i);
|
||||
buf.append(",");
|
||||
buf.append(Integer.toString(node.j));
|
||||
buf.append(node.j);
|
||||
buf.append(")");
|
||||
node = node.prev;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2018 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Abstract delta between a source and a target.
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public abstract class AbstractDelta<T> {
|
||||
private final Chunk<T> source;
|
||||
private final Chunk<T> target;
|
||||
private final DeltaType type;
|
||||
|
||||
public AbstractDelta(DeltaType type, Chunk<T> source, Chunk<T> target) {
|
||||
Objects.requireNonNull(source);
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(type);
|
||||
this.type = type;
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public Chunk<T> getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Chunk<T> getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public DeltaType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the chunk of this delta, to fit the target.
|
||||
* @param target
|
||||
* @throws PatchFailedException
|
||||
*/
|
||||
protected void verifyChunk(List<T> target) throws PatchFailedException {
|
||||
getSource().verify(target);
|
||||
}
|
||||
|
||||
public abstract void applyTo(List<T> target) throws PatchFailedException;
|
||||
|
||||
public abstract void restore(List<T> target);
|
||||
|
||||
/**
|
||||
* Create a new delta of the actual instance with customized chunk data.
|
||||
*/
|
||||
public abstract AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised);
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.source, this.target, this.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final AbstractDelta<?> other = (AbstractDelta<?>) obj;
|
||||
if (!Objects.equals(this.source, other.source)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.target, other.target)) {
|
||||
return false;
|
||||
}
|
||||
if (this.type != other.type) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Describes the change-delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param <T> The type of the compared elements in the data 'lines'.
|
||||
*/
|
||||
public final class ChangeDelta<T> extends AbstractDelta<T> {
|
||||
|
||||
/**
|
||||
* Creates a change delta with the two given chunks.
|
||||
*
|
||||
* @param source The source chunk. Must not be {@code null}.
|
||||
* @param target The target chunk. Must not be {@code null}.
|
||||
*/
|
||||
public ChangeDelta(Chunk<T> source, Chunk<T> target) {
|
||||
super(DeltaType.CHANGE, source, target);
|
||||
Objects.requireNonNull(source, "source must not be null");
|
||||
Objects.requireNonNull(target, "target must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verifyChunk(target);
|
||||
int position = getSource().getPosition();
|
||||
int size = getSource().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
int i = 0;
|
||||
for (T line : getTarget().getLines()) {
|
||||
target.add(position + i, line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
int position = getTarget().getPosition();
|
||||
int size = getTarget().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
int i = 0;
|
||||
for (T line : getSource().getLines()) {
|
||||
target.add(position + i, line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
+ getSource().getLines() + " to " + getTarget().getLines() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
|
||||
return new ChangeDelta(original, revised);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,56 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Holds the information about the part of text involved in the diff process
|
||||
*
|
||||
* <p>
|
||||
* Text is represented as <code>Object[]</code> because the diff engine is capable of handling more than plain ascci. In
|
||||
* fact, arrays or lists of any type that implements {@link java.lang.Object#hashCode hashCode()} and
|
||||
* {@link java.lang.Object#equals equals()} correctly can be subject to differencing using this library.
|
||||
* Text is represented as <code>Object[]</code> because the diff engine is capable of handling more
|
||||
* than plain ascci. In fact, arrays or lists of any type that implements
|
||||
* {@link java.lang.Object#hashCode hashCode()} and {@link java.lang.Object#equals equals()}
|
||||
* correctly can be subject to differencing using this library.
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com>Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
* @param <T> The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class Chunk<T> {
|
||||
|
||||
private final int position;
|
||||
private List<T> lines;
|
||||
private final List<Integer> changePosition;
|
||||
|
||||
/**
|
||||
* Creates a chunk and saves a copy of affected lines
|
||||
*
|
||||
* @param position the start position
|
||||
* @param lines the affected lines
|
||||
* @param changePosition the positions of changed lines
|
||||
*/
|
||||
public Chunk(int position, List<T> lines, List<Integer> changePosition) {
|
||||
this.position = position;
|
||||
this.lines = new ArrayList<>(lines);
|
||||
this.changePosition = changePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a chunk and saves a copy of affected lines
|
||||
@@ -46,8 +59,20 @@ public final class Chunk<T> {
|
||||
* @param lines the affected lines
|
||||
*/
|
||||
public Chunk(int position, List<T> lines) {
|
||||
this(position, lines, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a chunk and saves a copy of affected lines
|
||||
*
|
||||
* @param position the start position
|
||||
* @param lines the affected lines
|
||||
* @param changePosition the positions of changed lines
|
||||
*/
|
||||
public Chunk(int position, T[] lines, List<Integer> changePosition) {
|
||||
this.position = position;
|
||||
this.lines = lines;
|
||||
this.lines = Arrays.asList(lines);
|
||||
this.changePosition = changePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,14 +82,14 @@ public final class Chunk<T> {
|
||||
* @param lines the affected lines
|
||||
*/
|
||||
public Chunk(int position, T[] lines) {
|
||||
this.position = position;
|
||||
this.lines = Arrays.asList(lines);
|
||||
this(position, lines, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that this chunk's saved text matches the corresponding text in the given sequence.
|
||||
*
|
||||
* @param target the sequence to verify against.
|
||||
* @throws com.github.difflib.patch.PatchFailedException
|
||||
*/
|
||||
public void verify(List<T> target) throws PatchFailedException {
|
||||
if (position > target.size() || last() > target.size()) {
|
||||
@@ -96,6 +121,13 @@ public final class Chunk<T> {
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the positions of changed lines of chunk in the text
|
||||
*/
|
||||
public List<Integer> getChangePosition() {
|
||||
return changePosition;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return lines.size();
|
||||
}
|
||||
@@ -107,26 +139,11 @@ public final class Chunk<T> {
|
||||
return getPosition() + size() - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((lines == null) ? 0 : lines.hashCode());
|
||||
result = prime * result + position;
|
||||
result = prime * result + size();
|
||||
return result;
|
||||
return Objects.hash(lines, position, size());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes the delete-delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param <T> The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class DeleteDelta<T> extends AbstractDelta<T> {
|
||||
|
||||
/**
|
||||
* Creates a change delta with the two given chunks.
|
||||
*
|
||||
* @param original The original chunk. Must not be {@code null}.
|
||||
* @param revised The original chunk. Must not be {@code null}.
|
||||
*/
|
||||
public DeleteDelta(Chunk<T> original, Chunk<T> revised) {
|
||||
super(DeltaType.DELETE, original, revised);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verifyChunk(target);
|
||||
int position = getSource().getPosition();
|
||||
int size = getSource().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
int position = this.getTarget().getPosition();
|
||||
List<T> lines = this.getSource().getLines();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
target.add(position + i, lines.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[DeleteDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
+ getSource().getLines() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
|
||||
return new DeleteDelta(original, revised);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,18 @@
|
||||
package com.github.difflib.patch;
|
||||
|
||||
/**
|
||||
* Specifies the type of the delta.
|
||||
* Specifies the type of the delta. There are three types of modifications from
|
||||
* the original to get the revised text.
|
||||
*
|
||||
* CHANGE: a block of data of the original is replaced by another block of data.
|
||||
* DELETE: a block of data of the original is removed
|
||||
* INSERT: at a position of the original a block of data is inserted
|
||||
*
|
||||
* to be complete there is also
|
||||
*
|
||||
* EQUAL: a block of data of original and the revised text is equal
|
||||
*
|
||||
* which is no change at all.
|
||||
*
|
||||
*/
|
||||
public enum DeltaType {
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
/**
|
||||
* Base class for all exceptions emanating from this package.
|
||||
*
|
||||
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
|
||||
*/
|
||||
public class DiffException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DiffException() {
|
||||
}
|
||||
|
||||
public DiffException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2020 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This delta contains equal lines of data. Therefore nothing is to do in applyTo and restore.
|
||||
* @author tobens
|
||||
*/
|
||||
public class EqualDelta<T> extends AbstractDelta<T> {
|
||||
|
||||
public EqualDelta(Chunk<T> source, Chunk<T> target) {
|
||||
super(DeltaType.EQUAL, source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verifyChunk(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[EqualDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
+ getSource().getLines() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
|
||||
return new EqualDelta(original, revised);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes the add-delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param <T> The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class InsertDelta<T> extends AbstractDelta<T> {
|
||||
|
||||
/**
|
||||
* Creates an insert delta with the two given chunks.
|
||||
*
|
||||
* @param original The original chunk. Must not be {@code null}.
|
||||
* @param revised The original chunk. Must not be {@code null}.
|
||||
*/
|
||||
public InsertDelta(Chunk<T> original, Chunk<T> revised) {
|
||||
super(DeltaType.INSERT, original, revised);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verifyChunk(target);
|
||||
int position = this.getSource().getPosition();
|
||||
List<T> lines = this.getTarget().getLines();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
target.add(position + i, lines.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
int position = getTarget().getPosition();
|
||||
int size = getTarget().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[InsertDelta, position: " + getSource().getPosition()
|
||||
+ ", lines: " + getTarget().getLines() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
|
||||
return new InsertDelta(original, revised);
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,10 @@ limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import static com.github.difflib.patch.DeltaType.DELETE;
|
||||
import static com.github.difflib.patch.DeltaType.INSERT;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import static java.util.Comparator.comparing;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
@@ -32,11 +30,11 @@ import java.util.ListIterator;
|
||||
* Describes the patch holding all deltas between the original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
* @param <T> The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class Patch<T> {
|
||||
|
||||
private final List<Delta<T>> deltas;
|
||||
private final List<AbstractDelta<T>> deltas;
|
||||
|
||||
public Patch() {
|
||||
this(10);
|
||||
@@ -54,9 +52,9 @@ public final class Patch<T> {
|
||||
*/
|
||||
public List<T> applyTo(List<T> target) throws PatchFailedException {
|
||||
List<T> result = new ArrayList<>(target);
|
||||
ListIterator<Delta<T>> it = getDeltas().listIterator(deltas.size());
|
||||
ListIterator<AbstractDelta<T>> it = getDeltas().listIterator(deltas.size());
|
||||
while (it.hasPrevious()) {
|
||||
Delta<T> delta = it.previous();
|
||||
AbstractDelta<T> delta = it.previous();
|
||||
delta.applyTo(result);
|
||||
}
|
||||
return result;
|
||||
@@ -70,9 +68,9 @@ public final class Patch<T> {
|
||||
*/
|
||||
public List<T> restore(List<T> target) {
|
||||
List<T> result = new ArrayList<>(target);
|
||||
ListIterator<Delta<T>> it = getDeltas().listIterator(deltas.size());
|
||||
ListIterator<AbstractDelta<T>> it = getDeltas().listIterator(deltas.size());
|
||||
while (it.hasPrevious()) {
|
||||
Delta<T> delta = it.previous();
|
||||
AbstractDelta<T> delta = it.previous();
|
||||
delta.restore(result);
|
||||
}
|
||||
return result;
|
||||
@@ -83,7 +81,7 @@ public final class Patch<T> {
|
||||
*
|
||||
* @param delta the given delta
|
||||
*/
|
||||
public void addDelta(Delta<T> delta) {
|
||||
public void addDelta(AbstractDelta<T> delta) {
|
||||
deltas.add(delta);
|
||||
}
|
||||
|
||||
@@ -92,8 +90,8 @@ public final class Patch<T> {
|
||||
*
|
||||
* @return the deltas
|
||||
*/
|
||||
public List<Delta<T>> getDeltas() {
|
||||
Collections.sort(deltas, comparing(d -> d.getOriginal().getPosition()));
|
||||
public List<AbstractDelta<T>> getDeltas() {
|
||||
deltas.sort(comparing(d -> d.getSource().getPosition()));
|
||||
return deltas;
|
||||
}
|
||||
|
||||
@@ -103,10 +101,35 @@ public final class Patch<T> {
|
||||
}
|
||||
|
||||
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> changes) {
|
||||
Patch<T> patch = new Patch<>(changes.size());
|
||||
return generate(original, revised, changes, false);
|
||||
}
|
||||
|
||||
private static <T> Chunk<T> buildChunk(int start, int end, List<T> data) {
|
||||
return new Chunk<>(start, new ArrayList<>(data.subList(start, end)));
|
||||
}
|
||||
|
||||
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> _changes, boolean includeEquals) {
|
||||
Patch<T> patch = new Patch<>(_changes.size());
|
||||
int startOriginal = 0;
|
||||
int startRevised = 0;
|
||||
|
||||
List<Change> changes = _changes;
|
||||
|
||||
if (includeEquals) {
|
||||
changes = new ArrayList<Change>(_changes);
|
||||
Collections.sort(changes, comparing(d -> d.startOriginal));
|
||||
}
|
||||
|
||||
for (Change change : changes) {
|
||||
Chunk<T> orgChunk = new Chunk<>(change.startOriginal, new ArrayList<>(original.subList(change.startOriginal, change.endOriginal)));
|
||||
Chunk<T> revChunk = new Chunk<>(change.startRevised, new ArrayList<>(revised.subList(change.startRevised, change.endRevised)));
|
||||
|
||||
if (includeEquals && startOriginal < change.startOriginal) {
|
||||
patch.addDelta(new EqualDelta(
|
||||
buildChunk(startOriginal, change.startOriginal, original),
|
||||
buildChunk(startRevised, change.startRevised, revised)));
|
||||
}
|
||||
|
||||
Chunk<T> orgChunk = buildChunk(change.startOriginal, change.endOriginal, original);
|
||||
Chunk<T> revChunk = buildChunk(change.startRevised, change.endRevised, revised);
|
||||
switch (change.deltaType) {
|
||||
case DELETE:
|
||||
patch.addDelta(new DeleteDelta<>(orgChunk, revChunk));
|
||||
@@ -118,7 +141,17 @@ public final class Patch<T> {
|
||||
patch.addDelta(new ChangeDelta<>(orgChunk, revChunk));
|
||||
break;
|
||||
}
|
||||
|
||||
startOriginal = change.endOriginal;
|
||||
startRevised = change.endRevised;
|
||||
}
|
||||
|
||||
if (includeEquals && startOriginal < original.size()) {
|
||||
patch.addDelta(new EqualDelta(
|
||||
buildChunk(startOriginal, original.size(), original),
|
||||
buildChunk(startRevised, revised.size(), revised)));
|
||||
}
|
||||
|
||||
return patch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
/**
|
||||
* Thrown whenever a delta cannot be applied as a patch to a given text.
|
||||
*
|
||||
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
|
||||
*/
|
||||
public class PatchFailedException extends DiffException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PatchFailedException() {
|
||||
}
|
||||
|
||||
public PatchFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,22 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.text;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Describes the diff row in form [tag, oldLine, newLine) for showing the difference between two texts
|
||||
@@ -70,26 +67,11 @@ public final class DiffRow implements Serializable {
|
||||
return newLine;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((newLine == null) ? 0 : newLine.hashCode());
|
||||
result = prime * result + ((oldLine == null) ? 0 : oldLine.hashCode());
|
||||
result = prime * result + ((tag == null) ? 0 : tag.hashCode());
|
||||
return result;
|
||||
return Objects.hash(newLine, oldLine, tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
@@ -1,43 +1,39 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.text;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.DeleteDelta;
|
||||
import com.github.difflib.patch.Delta;
|
||||
import com.github.difflib.patch.InsertDelta;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.text.DiffRow.Tag;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* This class for generating DiffRows for side-by-sidy view. You can customize the way of generating. For example, show
|
||||
* inline diffs on not, ignoring white spaces or/and blank lines and so on. All parameters for generating are optional.
|
||||
* If you do not specify them, the class will use the default values.
|
||||
* This class for generating DiffRows for side-by-sidy view. You can customize the way of
|
||||
* generating. For example, show inline diffs on not, ignoring white spaces or/and blank lines and
|
||||
* so on. All parameters for generating are optional. If you do not specify them, the class will use
|
||||
* the default values.
|
||||
*
|
||||
* These values are: showInlineDiffs = false; ignoreWhiteSpaces = true; ignoreBlankLines = true; ...
|
||||
*
|
||||
@@ -46,18 +42,14 @@ import java.util.regex.Pattern;
|
||||
* ignoreWhiteSpaces(true).columnWidth(100).build();
|
||||
* </code>
|
||||
*/
|
||||
public class DiffRowGenerator {
|
||||
public static final Pattern SPLIT_BY_WORD_PATTERN = Pattern.compile("\\s+|[,.\\[\\](){}/\\\\*+\\-#]");
|
||||
|
||||
public static final BiPredicate<String, String> IGNORE_WHITESPACE_EQUALIZER = (original, revised)
|
||||
-> original.trim().replaceAll("\\s+", " ").equals(revised.trim().replaceAll("\\s+", " "));
|
||||
|
||||
public final class DiffRowGenerator {
|
||||
|
||||
public static final BiPredicate<String, String> DEFAULT_EQUALIZER = Object::equals;
|
||||
|
||||
/**
|
||||
* Splitting lines by word to achieve word by word diff checking.
|
||||
*/
|
||||
public static final Function<String, List<String>> SPLITTER_BY_WORD = line -> splitStringPreserveDelimiter(line, SPLIT_BY_WORD_PATTERN);
|
||||
|
||||
public static final BiPredicate<String, String> IGNORE_WHITESPACE_EQUALIZER = (original, revised)
|
||||
-> adjustWhitespace(original).equals(adjustWhitespace(revised));
|
||||
|
||||
public static final Function<String, String> LINE_NORMALIZER_FOR_HTML = StringUtils::normalize;
|
||||
|
||||
/**
|
||||
* Splitting lines by character to achieve char by char diff checking.
|
||||
@@ -69,16 +61,329 @@ public class DiffRowGenerator {
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
private final boolean showInlineDiffs;
|
||||
private final boolean ignoreWhiteSpaces;
|
||||
private final Function<Boolean, String> oldTag;
|
||||
private final Function<Boolean, String> newTag;
|
||||
private final Function<String, List<String>> inlineDiffSplitter;
|
||||
|
||||
public static final Pattern SPLIT_BY_WORD_PATTERN = Pattern.compile("\\s+|[,.\\[\\](){}/\\\\*+\\-#]");
|
||||
|
||||
/**
|
||||
* Splitting lines by word to achieve word by word diff checking.
|
||||
*/
|
||||
public static final Function<String, List<String>> SPLITTER_BY_WORD = line -> splitStringPreserveDelimiter(line, SPLIT_BY_WORD_PATTERN);
|
||||
public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
|
||||
|
||||
public static Builder create() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private static String adjustWhitespace(String raw) {
|
||||
return WHITESPACE_PATTERN.matcher(raw.trim()).replaceAll(" ");
|
||||
}
|
||||
|
||||
protected final static List<String> splitStringPreserveDelimiter(String str, Pattern SPLIT_PATTERN) {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (str != null) {
|
||||
Matcher matcher = SPLIT_PATTERN.matcher(str);
|
||||
int pos = 0;
|
||||
while (matcher.find()) {
|
||||
if (pos < matcher.start()) {
|
||||
list.add(str.substring(pos, matcher.start()));
|
||||
}
|
||||
list.add(matcher.group());
|
||||
pos = matcher.end();
|
||||
}
|
||||
if (pos < str.length()) {
|
||||
list.add(str.substring(pos));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the elements in the sequence with the given tag
|
||||
*
|
||||
* @param startPosition the position from which tag should start. The counting start from a
|
||||
* zero.
|
||||
* @param endPosition the position before which tag should should be closed.
|
||||
* @param tagGenerator the tag generator
|
||||
*/
|
||||
static void wrapInTag(List<String> sequence, int startPosition,
|
||||
int endPosition, Tag tag, BiFunction<Tag, Boolean, String> tagGenerator,
|
||||
Function<String, String> processDiffs, boolean replaceLinefeedWithSpace) {
|
||||
int endPos = endPosition;
|
||||
|
||||
while (endPos >= startPosition) {
|
||||
|
||||
//search position for end tag
|
||||
while (endPos > startPosition) {
|
||||
if (!"\n".equals(sequence.get(endPos - 1))) {
|
||||
break;
|
||||
} else if (replaceLinefeedWithSpace) {
|
||||
sequence.set(endPos - 1, " ");
|
||||
break;
|
||||
}
|
||||
endPos--;
|
||||
}
|
||||
|
||||
if (endPos == startPosition) {
|
||||
break;
|
||||
}
|
||||
|
||||
sequence.add(endPos, tagGenerator.apply(tag, false));
|
||||
if (processDiffs != null) {
|
||||
sequence.set(endPos - 1,
|
||||
processDiffs.apply(sequence.get(endPos - 1)));
|
||||
}
|
||||
endPos--;
|
||||
|
||||
//search position for end tag
|
||||
while (endPos > startPosition) {
|
||||
if ("\n".equals(sequence.get(endPos - 1))) {
|
||||
if (replaceLinefeedWithSpace) {
|
||||
sequence.set(endPos - 1, " ");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (processDiffs != null) {
|
||||
sequence.set(endPos - 1,
|
||||
processDiffs.apply(sequence.get(endPos - 1)));
|
||||
}
|
||||
endPos--;
|
||||
}
|
||||
|
||||
sequence.add(endPos, tagGenerator.apply(tag, true));
|
||||
endPos--;
|
||||
}
|
||||
}
|
||||
|
||||
private final int columnWidth;
|
||||
private final BiPredicate<String, String> equalizer;
|
||||
private final boolean ignoreWhiteSpaces;
|
||||
private final Function<String, List<String>> inlineDiffSplitter;
|
||||
private final boolean mergeOriginalRevised;
|
||||
private final BiFunction<Tag, Boolean, String> newTag;
|
||||
private final BiFunction<Tag, Boolean, String> oldTag;
|
||||
private final boolean reportLinesUnchanged;
|
||||
private final Function<String, String> lineNormalizer;
|
||||
private final Function<String, String> processDiffs;
|
||||
|
||||
private final boolean showInlineDiffs;
|
||||
private final boolean replaceOriginalLinefeedInChangesWithSpaces;
|
||||
|
||||
private DiffRowGenerator(Builder builder) {
|
||||
showInlineDiffs = builder.showInlineDiffs;
|
||||
ignoreWhiteSpaces = builder.ignoreWhiteSpaces;
|
||||
oldTag = builder.oldTag;
|
||||
newTag = builder.newTag;
|
||||
columnWidth = builder.columnWidth;
|
||||
mergeOriginalRevised = builder.mergeOriginalRevised;
|
||||
inlineDiffSplitter = builder.inlineDiffSplitter;
|
||||
|
||||
if (builder.equalizer != null) {
|
||||
equalizer = builder.equalizer;
|
||||
} else {
|
||||
equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER;
|
||||
}
|
||||
|
||||
reportLinesUnchanged = builder.reportLinesUnchanged;
|
||||
lineNormalizer = builder.lineNormalizer;
|
||||
processDiffs = builder.processDiffs;
|
||||
|
||||
replaceOriginalLinefeedInChangesWithSpaces = builder.replaceOriginalLinefeedInChangesWithSpaces;
|
||||
|
||||
Objects.requireNonNull(inlineDiffSplitter);
|
||||
Objects.requireNonNull(lineNormalizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DiffRows describing the difference between original and revised texts using the given
|
||||
* patch. Useful for displaying side-by-side diff.
|
||||
*
|
||||
* @param original the original text
|
||||
* @param revised the revised text
|
||||
* @return the DiffRows between original and revised texts
|
||||
*/
|
||||
public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) {
|
||||
return generateDiffRows(original, DiffUtils.diff(original, revised, equalizer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the DiffRows describing the difference between original and revised texts using the
|
||||
* given patch. Useful for displaying side-by-side diff.
|
||||
*
|
||||
* @param original the original text
|
||||
* @param patch the given patch
|
||||
* @return the DiffRows between original and revised texts
|
||||
*/
|
||||
public List<DiffRow> generateDiffRows(final List<String> original, Patch<String> patch) {
|
||||
List<DiffRow> diffRows = new ArrayList<>();
|
||||
int endPos = 0;
|
||||
final List<AbstractDelta<String>> deltaList = patch.getDeltas();
|
||||
for (AbstractDelta<String> delta : deltaList) {
|
||||
Chunk<String> orig = delta.getSource();
|
||||
Chunk<String> rev = delta.getTarget();
|
||||
|
||||
for (String line : original.subList(endPos, orig.getPosition())) {
|
||||
diffRows.add(buildDiffRow(Tag.EQUAL, line, line));
|
||||
}
|
||||
|
||||
// Inserted DiffRow
|
||||
if (delta.getType() == DeltaType.INSERT) {
|
||||
endPos = orig.last() + 1;
|
||||
for (String line : rev.getLines()) {
|
||||
diffRows.add(buildDiffRow(Tag.INSERT, "", line));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deleted DiffRow
|
||||
if (delta.getType() == DeltaType.DELETE) {
|
||||
endPos = orig.last() + 1;
|
||||
for (String line : orig.getLines()) {
|
||||
diffRows.add(buildDiffRow(Tag.DELETE, line, ""));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (showInlineDiffs) {
|
||||
diffRows.addAll(generateInlineDiffs(delta));
|
||||
} else {
|
||||
for (int j = 0; j < Math.max(orig.size(), rev.size()); j++) {
|
||||
diffRows.add(buildDiffRow(Tag.CHANGE,
|
||||
orig.getLines().size() > j ? orig.getLines().get(j) : "",
|
||||
rev.getLines().size() > j ? rev.getLines().get(j) : ""));
|
||||
}
|
||||
}
|
||||
endPos = orig.last() + 1;
|
||||
}
|
||||
|
||||
// Copy the final matching chunk if any.
|
||||
for (String line : original.subList(endPos, original.size())) {
|
||||
diffRows.add(buildDiffRow(Tag.EQUAL, line, line));
|
||||
}
|
||||
return diffRows;
|
||||
}
|
||||
|
||||
private DiffRow buildDiffRow(Tag type, String orgline, String newline) {
|
||||
if (reportLinesUnchanged) {
|
||||
return new DiffRow(type, orgline, newline);
|
||||
} else {
|
||||
String wrapOrg = preprocessLine(orgline);
|
||||
if (Tag.DELETE == type) {
|
||||
if (mergeOriginalRevised || showInlineDiffs) {
|
||||
wrapOrg = oldTag.apply(type, true) + wrapOrg + oldTag.apply(type, false);
|
||||
}
|
||||
}
|
||||
String wrapNew = preprocessLine(newline);
|
||||
if (Tag.INSERT == type) {
|
||||
if (mergeOriginalRevised) {
|
||||
wrapOrg = newTag.apply(type, true) + wrapNew + newTag.apply(type, false);
|
||||
} else if (showInlineDiffs) {
|
||||
wrapNew = newTag.apply(type, true) + wrapNew + newTag.apply(type, false);
|
||||
}
|
||||
}
|
||||
return new DiffRow(type, wrapOrg, wrapNew);
|
||||
}
|
||||
}
|
||||
|
||||
private DiffRow buildDiffRowWithoutNormalizing(Tag type, String orgline, String newline) {
|
||||
return new DiffRow(type,
|
||||
StringUtils.wrapText(orgline, columnWidth),
|
||||
StringUtils.wrapText(newline, columnWidth));
|
||||
}
|
||||
|
||||
List<String> normalizeLines(List<String> list) {
|
||||
return reportLinesUnchanged
|
||||
? list
|
||||
: list.stream()
|
||||
.map(lineNormalizer::apply)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the inline diffs for given delta
|
||||
*
|
||||
* @param delta the given delta
|
||||
*/
|
||||
private List<DiffRow> generateInlineDiffs(AbstractDelta<String> delta) {
|
||||
List<String> orig = normalizeLines(delta.getSource().getLines());
|
||||
List<String> rev = normalizeLines(delta.getTarget().getLines());
|
||||
List<String> origList;
|
||||
List<String> revList;
|
||||
String joinedOrig = String.join("\n", orig);
|
||||
String joinedRev = String.join("\n", rev);
|
||||
|
||||
origList = inlineDiffSplitter.apply(joinedOrig);
|
||||
revList = inlineDiffSplitter.apply(joinedRev);
|
||||
|
||||
List<AbstractDelta<String>> inlineDeltas = DiffUtils.diff(origList, revList, equalizer).getDeltas();
|
||||
|
||||
Collections.reverse(inlineDeltas);
|
||||
for (AbstractDelta<String> inlineDelta : inlineDeltas) {
|
||||
Chunk<String> inlineOrig = inlineDelta.getSource();
|
||||
Chunk<String> inlineRev = inlineDelta.getTarget();
|
||||
if (inlineDelta.getType() == DeltaType.DELETE) {
|
||||
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
|
||||
.getPosition()
|
||||
+ inlineOrig.size(), Tag.DELETE, oldTag, processDiffs, replaceOriginalLinefeedInChangesWithSpaces && mergeOriginalRevised);
|
||||
} else if (inlineDelta.getType() == DeltaType.INSERT) {
|
||||
if (mergeOriginalRevised) {
|
||||
origList.addAll(inlineOrig.getPosition(),
|
||||
revList.subList(inlineRev.getPosition(),
|
||||
inlineRev.getPosition() + inlineRev.size()));
|
||||
wrapInTag(origList, inlineOrig.getPosition(),
|
||||
inlineOrig.getPosition() + inlineRev.size(),
|
||||
Tag.INSERT, newTag, processDiffs, false);
|
||||
} else {
|
||||
wrapInTag(revList, inlineRev.getPosition(),
|
||||
inlineRev.getPosition() + inlineRev.size(),
|
||||
Tag.INSERT, newTag, processDiffs, false);
|
||||
}
|
||||
} else if (inlineDelta.getType() == DeltaType.CHANGE) {
|
||||
if (mergeOriginalRevised) {
|
||||
origList.addAll(inlineOrig.getPosition() + inlineOrig.size(),
|
||||
revList.subList(inlineRev.getPosition(),
|
||||
inlineRev.getPosition() + inlineRev.size()));
|
||||
wrapInTag(origList, inlineOrig.getPosition() + inlineOrig.size(),
|
||||
inlineOrig.getPosition() + inlineOrig.size() + inlineRev.size(),
|
||||
Tag.CHANGE, newTag, processDiffs, false);
|
||||
} else {
|
||||
wrapInTag(revList, inlineRev.getPosition(),
|
||||
inlineRev.getPosition() + inlineRev.size(),
|
||||
Tag.CHANGE, newTag, processDiffs, false);
|
||||
}
|
||||
wrapInTag(origList, inlineOrig.getPosition(),
|
||||
inlineOrig.getPosition() + inlineOrig.size(),
|
||||
Tag.CHANGE, oldTag, processDiffs, replaceOriginalLinefeedInChangesWithSpaces && mergeOriginalRevised);
|
||||
}
|
||||
}
|
||||
StringBuilder origResult = new StringBuilder();
|
||||
StringBuilder revResult = new StringBuilder();
|
||||
for (String character : origList) {
|
||||
origResult.append(character);
|
||||
}
|
||||
for (String character : revList) {
|
||||
revResult.append(character);
|
||||
}
|
||||
|
||||
List<String> original = Arrays.asList(origResult.toString().split("\n"));
|
||||
List<String> revised = Arrays.asList(revResult.toString().split("\n"));
|
||||
List<DiffRow> diffRows = new ArrayList<>();
|
||||
for (int j = 0; j < Math.max(original.size(), revised.size()); j++) {
|
||||
diffRows.
|
||||
add(buildDiffRowWithoutNormalizing(Tag.CHANGE,
|
||||
original.size() > j ? original.get(j) : "",
|
||||
revised.size() > j ? revised.get(j) : ""));
|
||||
}
|
||||
return diffRows;
|
||||
}
|
||||
|
||||
private String preprocessLine(String line) {
|
||||
if (columnWidth == 0) {
|
||||
return lineNormalizer.apply(line);
|
||||
} else {
|
||||
return StringUtils.wrapText(lineNormalizer.apply(line), columnWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class used for building the DiffRowGenerator.
|
||||
@@ -91,13 +396,19 @@ public class DiffRowGenerator {
|
||||
private boolean showInlineDiffs = false;
|
||||
private boolean ignoreWhiteSpaces = false;
|
||||
|
||||
private Function<Boolean, String> oldTag = f -> f ? "<span class=\"editOldInline\">" : "</span>";
|
||||
private Function<Boolean, String> newTag = f -> f ? "<span class=\"editNewInline\">" : "</span>";
|
||||
private BiFunction<Tag, Boolean, String> oldTag
|
||||
= (tag, f) -> f ? "<span class=\"editOldInline\">" : "</span>";
|
||||
private BiFunction<Tag, Boolean, String> newTag
|
||||
= (tag, f) -> f ? "<span class=\"editNewInline\">" : "</span>";
|
||||
|
||||
private int columnWidth = 0;
|
||||
private boolean mergeOriginalRevised = false;
|
||||
private boolean reportLinesUnchanged = false;
|
||||
private Function<String, List<String>> inlineDiffSplitter = SPLITTER_BY_CHARACTER;
|
||||
private Function<String, String> lineNormalizer = LINE_NORMALIZER_FOR_HTML;
|
||||
private Function<String, String> processDiffs = null;
|
||||
private BiPredicate<String, String> equalizer = null;
|
||||
private boolean replaceOriginalLinefeedInChangesWithSpaces = false;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
@@ -125,7 +436,8 @@ public class DiffRowGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the originial old and new text lines to Diffrow without any additional processing.
|
||||
* Give the originial old and new text lines to Diffrow without any additional processing
|
||||
* and without any tags to highlight the change.
|
||||
*
|
||||
* @param val the value to set. Default: false.
|
||||
* @return builder with configured reportLinesUnWrapped parameter
|
||||
@@ -138,11 +450,33 @@ public class DiffRowGenerator {
|
||||
/**
|
||||
* Generator for Old-Text-Tags.
|
||||
*
|
||||
* @param tag the tag to set. Without angle brackets. Default: span.
|
||||
* @param generator the tag generator
|
||||
* @return builder with configured ignoreBlankLines parameter
|
||||
*/
|
||||
public Builder oldTag(BiFunction<Tag, Boolean, String> generator) {
|
||||
this.oldTag = generator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generator for Old-Text-Tags.
|
||||
*
|
||||
* @param generator the tag generator
|
||||
* @return builder with configured ignoreBlankLines parameter
|
||||
*/
|
||||
public Builder oldTag(Function<Boolean, String> generator) {
|
||||
this.oldTag = generator;
|
||||
this.oldTag = (tag, f) -> generator.apply(f);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generator for New-Text-Tags.
|
||||
*
|
||||
* @param generator
|
||||
* @return
|
||||
*/
|
||||
public Builder newTag(BiFunction<Tag, Boolean, String> generator) {
|
||||
this.newTag = generator;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -153,15 +487,27 @@ public class DiffRowGenerator {
|
||||
* @return
|
||||
*/
|
||||
public Builder newTag(Function<Boolean, String> generator) {
|
||||
this.newTag = generator;
|
||||
this.newTag = (tag, f) -> generator.apply(f);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column with of generated lines of original and revised texts.
|
||||
* Processor for diffed text parts. Here e.g. whitecharacters could be replaced by something
|
||||
* visible.
|
||||
*
|
||||
* @param width the width to set. Making it < 0 doesn't have any sense. Default 80. @return builder with config
|
||||
* ured ignoreBlankLines parameter
|
||||
* @param processDiffs
|
||||
* @return
|
||||
*/
|
||||
public Builder processDiffs(Function<String, String> processDiffs) {
|
||||
this.processDiffs = processDiffs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the column width of generated lines of original and revised texts.
|
||||
*
|
||||
* @param width the width to set. Making it < 0 doesn't make any sense. Default 80.
|
||||
* @return builder with config of column width
|
||||
*/
|
||||
public Builder columnWidth(int width) {
|
||||
if (width >= 0) {
|
||||
@@ -180,7 +526,8 @@ public class DiffRowGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the complete result within the original text. This makes sense for one line display.
|
||||
* Merge the complete result within the original text. This makes sense for one line
|
||||
* display.
|
||||
*
|
||||
* @param mergeOriginalRevised
|
||||
* @return
|
||||
@@ -191,250 +538,66 @@ public class DiffRowGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Per default each character is separatly processed. This variant introduces processing by word, which should
|
||||
* deliver no in word changes.
|
||||
* Per default each character is separatly processed. This variant introduces processing by
|
||||
* word, which does not deliver in word changes. Therefore the whole word will be tagged as
|
||||
* changed:
|
||||
*
|
||||
* <pre>
|
||||
* false: (aBa : aba) -- changed: a(B)a : a(b)a
|
||||
* true: (aBa : aba) -- changed: (aBa) : (aba)
|
||||
* </pre>
|
||||
*/
|
||||
public Builder inlineDiffByWord(boolean inlineDiffByWord) {
|
||||
inlineDiffSplitter = inlineDiffByWord?SPLITTER_BY_WORD:SPLITTER_BY_CHARACTER;
|
||||
inlineDiffSplitter = inlineDiffByWord ? SPLITTER_BY_WORD : SPLITTER_BY_CHARACTER;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* To provide some customized splitting a splitter can be provided. Here someone could think
|
||||
* about sentence splitter, comma splitter or stuff like that.
|
||||
*
|
||||
* @param inlineDiffSplitter
|
||||
* @return
|
||||
*/
|
||||
public Builder inlineDiffBySplitter(Function<String, List<String>> inlineDiffSplitter) {
|
||||
this.inlineDiffSplitter = inlineDiffSplitter;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder create() {
|
||||
return new Builder();
|
||||
}
|
||||
/**
|
||||
* By default DiffRowGenerator preprocesses lines for HTML output. Tabs and special HTML
|
||||
* characters like "<" are replaced with its encoded value. To change this you can
|
||||
* provide a customized line normalizer here.
|
||||
*
|
||||
* @param lineNormalizer
|
||||
* @return
|
||||
*/
|
||||
public Builder lineNormalizer(Function<String, String> lineNormalizer) {
|
||||
this.lineNormalizer = lineNormalizer;
|
||||
return this;
|
||||
}
|
||||
|
||||
private DiffRowGenerator(Builder builder) {
|
||||
showInlineDiffs = builder.showInlineDiffs;
|
||||
ignoreWhiteSpaces = builder.ignoreWhiteSpaces;
|
||||
oldTag = builder.oldTag;
|
||||
newTag = builder.newTag;
|
||||
columnWidth = builder.columnWidth;
|
||||
mergeOriginalRevised = builder.mergeOriginalRevised;
|
||||
inlineDiffSplitter = builder.inlineDiffSplitter;
|
||||
equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER;
|
||||
reportLinesUnchanged = builder.reportLinesUnchanged;
|
||||
/**
|
||||
* Provide an equalizer for diff processing.
|
||||
*
|
||||
* @param equalizer equalizer for diff processing.
|
||||
* @return builder with configured equalizer parameter
|
||||
*/
|
||||
public Builder equalizer(BiPredicate<String, String> equalizer) {
|
||||
this.equalizer = equalizer;
|
||||
return this;
|
||||
}
|
||||
|
||||
Objects.requireNonNull(inlineDiffSplitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DiffRows describing the difference between original and revised texts using the given patch. Useful for
|
||||
* displaying side-by-side diff.
|
||||
*
|
||||
* @param original the original text
|
||||
* @param revised the revised text
|
||||
* @return the DiffRows between original and revised texts
|
||||
*/
|
||||
public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) throws DiffException {
|
||||
return generateDiffRows(original, DiffUtils.diff(original, revised, equalizer));
|
||||
}
|
||||
|
||||
private String preprocessLine(String line) {
|
||||
if (columnWidth == 0) {
|
||||
return StringUtils.normalize(line);
|
||||
} else {
|
||||
return StringUtils.wrapText(StringUtils.normalize(line), columnWidth);
|
||||
/**
|
||||
* Sometimes it happens that a change contains multiple lines. If there is no correspondence
|
||||
* in old and new. To keep the merged line more readable the linefeeds could be replaced
|
||||
* by spaces.
|
||||
* @param replace
|
||||
* @return
|
||||
*/
|
||||
public Builder replaceOriginalLinefeedInChangesWithSpaces(boolean replace) {
|
||||
this.replaceOriginalLinefeedInChangesWithSpaces = replace;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private DiffRow buildDiffRow(Tag type, String orgline, String newline) {
|
||||
if (reportLinesUnchanged) {
|
||||
return new DiffRow(type, orgline, newline);
|
||||
} else {
|
||||
String wrapOrg = preprocessLine(orgline);
|
||||
if (Tag.DELETE == type) {
|
||||
if (mergeOriginalRevised || showInlineDiffs) {
|
||||
wrapOrg = oldTag.apply(true) + wrapOrg + oldTag.apply(false);
|
||||
}
|
||||
}
|
||||
String wrapNew = preprocessLine(newline);
|
||||
if (Tag.INSERT == type) {
|
||||
if (mergeOriginalRevised) {
|
||||
wrapOrg = newTag.apply(true) + wrapNew + newTag.apply(false);
|
||||
} else if (showInlineDiffs) {
|
||||
wrapNew = newTag.apply(true) + wrapNew + newTag.apply(false);
|
||||
}
|
||||
}
|
||||
return new DiffRow(type, wrapOrg, wrapNew);
|
||||
}
|
||||
}
|
||||
|
||||
private DiffRow buildDiffRowWithoutNormalizing(Tag type, String orgline, String newline) {
|
||||
return new DiffRow(type,
|
||||
StringUtils.wrapText(orgline, columnWidth),
|
||||
StringUtils.wrapText(newline, columnWidth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the DiffRows describing the difference between original and revised texts using the given patch. Useful
|
||||
* for displaying side-by-side diff.
|
||||
*
|
||||
* @param original the original text
|
||||
* @param revised the revised text
|
||||
* @param patch the given patch
|
||||
* @return the DiffRows between original and revised texts
|
||||
*/
|
||||
public List<DiffRow> generateDiffRows(final List<String> original, Patch<String> patch) throws DiffException {
|
||||
List<DiffRow> diffRows = new ArrayList<>();
|
||||
int endPos = 0;
|
||||
final List<Delta<String>> deltaList = patch.getDeltas();
|
||||
for (int i = 0; i < deltaList.size(); i++) {
|
||||
Delta<String> delta = deltaList.get(i);
|
||||
Chunk<String> orig = delta.getOriginal();
|
||||
Chunk<String> rev = delta.getRevised();
|
||||
|
||||
for (String line : original.subList(endPos, orig.getPosition())) {
|
||||
diffRows.add(buildDiffRow(Tag.EQUAL, line, line));
|
||||
}
|
||||
|
||||
// Inserted DiffRow
|
||||
if (delta instanceof InsertDelta) {
|
||||
endPos = orig.last() + 1;
|
||||
for (String line : (List<String>) rev.getLines()) {
|
||||
diffRows.add(buildDiffRow(Tag.INSERT, "", line));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deleted DiffRow
|
||||
if (delta instanceof DeleteDelta) {
|
||||
endPos = orig.last() + 1;
|
||||
for (String line : (List<String>) orig.getLines()) {
|
||||
diffRows.add(buildDiffRow(Tag.DELETE, line, ""));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (showInlineDiffs) {
|
||||
diffRows.addAll(generateInlineDiffs(delta));
|
||||
} else {
|
||||
for (int j = 0; j < Math.max(orig.size(), rev.size()); j++) {
|
||||
diffRows.add(buildDiffRow(Tag.CHANGE,
|
||||
orig.getLines().size() > j ? orig.getLines().get(j) : "",
|
||||
rev.getLines().size() > j ? rev.getLines().get(j) : ""));
|
||||
}
|
||||
}
|
||||
endPos = orig.last() + 1;
|
||||
}
|
||||
|
||||
// Copy the final matching chunk if any.
|
||||
for (String line : original.subList(endPos, original.size())) {
|
||||
diffRows.add(buildDiffRow(Tag.EQUAL, line, line));
|
||||
}
|
||||
return diffRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the inline diffs for given delta
|
||||
*
|
||||
* @param delta the given delta
|
||||
*/
|
||||
private List<DiffRow> generateInlineDiffs(Delta<String> delta) throws DiffException {
|
||||
List<String> orig = StringUtils.normalize(delta.getOriginal().getLines());
|
||||
List<String> rev = StringUtils.normalize(delta.getRevised().getLines());
|
||||
List<String> origList;
|
||||
List<String> revList;
|
||||
String joinedOrig = String.join("\n", orig);
|
||||
String joinedRev = String.join("\n", rev);
|
||||
|
||||
origList = inlineDiffSplitter.apply(joinedOrig);
|
||||
revList = inlineDiffSplitter.apply(joinedRev);
|
||||
|
||||
List<Delta<String>> inlineDeltas = DiffUtils.diff(origList, revList).getDeltas();
|
||||
|
||||
Collections.reverse(inlineDeltas);
|
||||
for (Delta<String> inlineDelta : inlineDeltas) {
|
||||
Chunk<String> inlineOrig = inlineDelta.getOriginal();
|
||||
Chunk<String> inlineRev = inlineDelta.getRevised();
|
||||
if (inlineDelta instanceof DeleteDelta) {
|
||||
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
|
||||
.getPosition()
|
||||
+ inlineOrig.size() + 1, oldTag);
|
||||
} else if (inlineDelta instanceof InsertDelta) {
|
||||
if (mergeOriginalRevised) {
|
||||
origList.addAll(inlineOrig.getPosition(),
|
||||
revList.subList(inlineRev.getPosition(), inlineRev.getPosition()
|
||||
+ inlineRev.size()));
|
||||
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig.getPosition()
|
||||
+ inlineRev.size() + 1, newTag);
|
||||
} else {
|
||||
wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
|
||||
+ inlineRev.size() + 1, newTag);
|
||||
}
|
||||
} else if (inlineDelta instanceof ChangeDelta) {
|
||||
if (mergeOriginalRevised) {
|
||||
origList.addAll(inlineOrig.getPosition() + inlineOrig.size(),
|
||||
revList.subList(inlineRev.getPosition(), inlineRev.getPosition()
|
||||
+ inlineRev.size()));
|
||||
wrapInTag(origList, inlineOrig.getPosition() + inlineOrig.size(), inlineOrig.getPosition() + inlineOrig.size()
|
||||
+ inlineRev.size() + 1, newTag);
|
||||
} else {
|
||||
wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
|
||||
+ inlineRev.size() + 1, newTag);
|
||||
}
|
||||
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
|
||||
.getPosition()
|
||||
+ inlineOrig.size() + 1, oldTag);
|
||||
}
|
||||
}
|
||||
StringBuilder origResult = new StringBuilder();
|
||||
StringBuilder revResult = new StringBuilder();
|
||||
for (String character : origList) {
|
||||
origResult.append(character);
|
||||
}
|
||||
for (String character : revList) {
|
||||
revResult.append(character);
|
||||
}
|
||||
|
||||
List<String> original = Arrays.asList(origResult.toString().split("\n"));
|
||||
List<String> revised = Arrays.asList(revResult.toString().split("\n"));
|
||||
List<DiffRow> diffRows = new ArrayList<>();
|
||||
for (int j = 0; j < Math.max(original.size(), revised.size()); j++) {
|
||||
diffRows.
|
||||
add(buildDiffRowWithoutNormalizing(Tag.CHANGE,
|
||||
original.size() > j ? original.get(j) : "",
|
||||
revised.size() > j ? revised.get(j) : ""));
|
||||
}
|
||||
return diffRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the elements in the sequence with the given tag
|
||||
*
|
||||
* @param startPosition the position from which tag should start. The counting start from a zero.
|
||||
* @param endPosition the position before which tag should should be closed.
|
||||
* @param tag the tag name without angle brackets, just a word
|
||||
* @param cssClass the optional css class
|
||||
*/
|
||||
public static void wrapInTag(List<String> sequence, int startPosition,
|
||||
int endPosition, Function<Boolean, String> generator) {
|
||||
sequence.add(startPosition, generator.apply(true));
|
||||
sequence.add(endPosition, generator.apply(false));
|
||||
}
|
||||
|
||||
protected final static List<String> splitStringPreserveDelimiter(String str, Pattern SPLIT_PATTERN) {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (str != null) {
|
||||
Matcher matcher = SPLIT_PATTERN.matcher(str);
|
||||
int pos = 0;
|
||||
while (matcher.find()) {
|
||||
if (pos < matcher.start()) {
|
||||
list.add(str.substring(pos, matcher.start()));
|
||||
}
|
||||
list.add(matcher.group());
|
||||
pos = matcher.end();
|
||||
}
|
||||
if (pos < str.length()) {
|
||||
list.add(str.substring(pos));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
/*
|
||||
* Copyright 2009-2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.text;
|
||||
|
||||
@@ -38,12 +34,6 @@ final class StringUtils {
|
||||
return htmlEntites(str).replace("\t", " ");
|
||||
}
|
||||
|
||||
public static List<String> normalize(List<String> list) {
|
||||
return list.stream()
|
||||
.map(StringUtils::normalize)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public static List<String> wrapText(List<String> list, int columnWidth) {
|
||||
return list.stream()
|
||||
.map(line -> wrapText(line, columnWidth))
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public final class UnifiedDiff {
|
||||
|
||||
private String header;
|
||||
private String tail;
|
||||
private final List<UnifiedDiffFile> files = new ArrayList<>();
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
void addFile(UnifiedDiffFile file) {
|
||||
files.add(file);
|
||||
}
|
||||
|
||||
public List<UnifiedDiffFile> getFiles() {
|
||||
return Collections.unmodifiableList(files);
|
||||
}
|
||||
|
||||
void setTailTxt(String tailTxt) {
|
||||
this.tail = tailTxt;
|
||||
}
|
||||
|
||||
public String getTail() {
|
||||
return tail;
|
||||
}
|
||||
|
||||
public List<String> spplyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException {
|
||||
UnifiedDiffFile file = files.stream()
|
||||
.filter(diff -> findFile.test(diff.getFromFile()))
|
||||
.findFirst().orElse(null);
|
||||
if (file != null) {
|
||||
return file.getPatch().applyTo(originalLines);
|
||||
} else {
|
||||
return originalLines;
|
||||
}
|
||||
}
|
||||
|
||||
public static UnifiedDiff from(String header, String tail, UnifiedDiffFile... files) {
|
||||
UnifiedDiff diff = new UnifiedDiff();
|
||||
diff.setHeader(header);
|
||||
diff.setTailTxt(tail);
|
||||
for (UnifiedDiffFile file : files) {
|
||||
diff.addFile(file);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public final class UnifiedDiffFile {
|
||||
|
||||
private String diffCommand;
|
||||
private String fromFile;
|
||||
private String fromTimestamp;
|
||||
private String toFile;
|
||||
private String toTimestamp;
|
||||
private String index;
|
||||
private String newFileMode;
|
||||
private String deletedFileMode;
|
||||
private Patch<String> patch = new Patch<>();
|
||||
|
||||
public String getDiffCommand() {
|
||||
return diffCommand;
|
||||
}
|
||||
|
||||
public void setDiffCommand(String diffCommand) {
|
||||
this.diffCommand = diffCommand;
|
||||
}
|
||||
|
||||
public String getFromFile() {
|
||||
return fromFile;
|
||||
}
|
||||
|
||||
public void setFromFile(String fromFile) {
|
||||
this.fromFile = fromFile;
|
||||
}
|
||||
|
||||
public String getToFile() {
|
||||
return toFile;
|
||||
}
|
||||
|
||||
public void setToFile(String toFile) {
|
||||
this.toFile = toFile;
|
||||
}
|
||||
|
||||
public void setIndex(String index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public Patch<String> getPatch() {
|
||||
return patch;
|
||||
}
|
||||
|
||||
public String getFromTimestamp() {
|
||||
return fromTimestamp;
|
||||
}
|
||||
|
||||
public void setFromTimestamp(String fromTimestamp) {
|
||||
this.fromTimestamp = fromTimestamp;
|
||||
}
|
||||
|
||||
public String getToTimestamp() {
|
||||
return toTimestamp;
|
||||
}
|
||||
|
||||
public void setToTimestamp(String toTimestamp) {
|
||||
this.toTimestamp = toTimestamp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static UnifiedDiffFile from(String fromFile, String toFile, Patch<String> patch) {
|
||||
UnifiedDiffFile file = new UnifiedDiffFile();
|
||||
file.setFromFile(fromFile);
|
||||
file.setToFile(toFile);
|
||||
file.patch = patch;
|
||||
return file;
|
||||
}
|
||||
|
||||
public void setNewFileMode(String newFileMode) {
|
||||
this.newFileMode = newFileMode;
|
||||
}
|
||||
|
||||
public String getNewFileMode() {
|
||||
return newFileMode;
|
||||
}
|
||||
|
||||
public String getDeletedFileMode() {
|
||||
return deletedFileMode;
|
||||
}
|
||||
|
||||
public void setDeletedFileMode(String deletedFileMode) {
|
||||
this.deletedFileMode = deletedFileMode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public class UnifiedDiffParserException extends RuntimeException {
|
||||
|
||||
public UnifiedDiffParserException() {
|
||||
}
|
||||
|
||||
public UnifiedDiffParserException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnifiedDiffParserException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UnifiedDiffParserException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public UnifiedDiffParserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.MatchResult;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public final class UnifiedDiffReader {
|
||||
|
||||
static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern.compile("^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@");
|
||||
static final Pattern TIMESTAMP_REGEXP = Pattern.compile("(\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}\\.\\d{3,})(?: [+-]\\d+)?");
|
||||
|
||||
private final InternalUnifiedDiffReader READER;
|
||||
private final UnifiedDiff data = new UnifiedDiff();
|
||||
|
||||
private final UnifiedDiffLine DIFF_COMMAND = new UnifiedDiffLine(true, "^diff\\s", this::processDiff);
|
||||
private final UnifiedDiffLine INDEX = new UnifiedDiffLine(true, "^index\\s[\\da-zA-Z]+\\.\\.[\\da-zA-Z]+(\\s(\\d+))?$", this::processIndex);
|
||||
private final UnifiedDiffLine FROM_FILE = new UnifiedDiffLine(true, "^---\\s", this::processFromFile);
|
||||
private final UnifiedDiffLine TO_FILE = new UnifiedDiffLine(true, "^\\+\\+\\+\\s", this::processToFile);
|
||||
|
||||
private final UnifiedDiffLine NEW_FILE_MODE = new UnifiedDiffLine(true, "^new\\sfile\\smode\\s(\\d+)", this::processNewFileMode);
|
||||
|
||||
private final UnifiedDiffLine DELETED_FILE_MODE = new UnifiedDiffLine(true, "^deleted\\sfile\\smode\\s(\\d+)", this::processDeletedFileMode);
|
||||
|
||||
private final UnifiedDiffLine CHUNK = new UnifiedDiffLine(false, UNIFIED_DIFF_CHUNK_REGEXP, this::processChunk);
|
||||
private final UnifiedDiffLine LINE_NORMAL = new UnifiedDiffLine("^\\s", this::processNormalLine);
|
||||
private final UnifiedDiffLine LINE_DEL = new UnifiedDiffLine("^-", this::processDelLine);
|
||||
private final UnifiedDiffLine LINE_ADD = new UnifiedDiffLine("^\\+", this::processAddLine);
|
||||
|
||||
private UnifiedDiffFile actualFile;
|
||||
|
||||
UnifiedDiffReader(Reader reader) {
|
||||
this.READER = new InternalUnifiedDiffReader(reader);
|
||||
}
|
||||
|
||||
// schema = [[/^\s+/, normal], [/^diff\s/, start], [/^new file mode \d+$/, new_file],
|
||||
// [/^deleted file mode \d+$/, deleted_file], [/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/, index],
|
||||
// [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk],
|
||||
// [/^-/, del], [/^\+/, add], [/^\\ No newline at end of file$/, eof]];
|
||||
private UnifiedDiff parse() throws IOException, UnifiedDiffParserException {
|
||||
String headerTxt = "";
|
||||
LOG.log(Level.FINE, "header parsing");
|
||||
String line = null;
|
||||
while (READER.ready()) {
|
||||
line = READER.readLine();
|
||||
LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
if (DIFF_COMMAND.validLine(line) || INDEX.validLine(line)
|
||||
|| FROM_FILE.validLine(line) || TO_FILE.validLine(line)
|
||||
|| NEW_FILE_MODE.validLine(line)) {
|
||||
break;
|
||||
} else {
|
||||
headerTxt += line + "\n";
|
||||
}
|
||||
}
|
||||
if (!"".equals(headerTxt)) {
|
||||
data.setHeader(headerTxt);
|
||||
}
|
||||
|
||||
while (line != null) {
|
||||
if (!CHUNK.validLine(line)) {
|
||||
initFileIfNecessary();
|
||||
while (line != null && !CHUNK.validLine(line)) {
|
||||
if (processLine(line, DIFF_COMMAND, INDEX, FROM_FILE, TO_FILE, NEW_FILE_MODE, DELETED_FILE_MODE) == false) {
|
||||
throw new UnifiedDiffParserException("expected file start line not found");
|
||||
}
|
||||
line = READER.readLine();
|
||||
}
|
||||
}
|
||||
if (line != null) {
|
||||
processLine(line, CHUNK);
|
||||
while ((line = READER.readLine()) != null) {
|
||||
if (processLine(line, LINE_NORMAL, LINE_ADD, LINE_DEL) == false) {
|
||||
throw new UnifiedDiffParserException("expected data line not found");
|
||||
}
|
||||
if ((originalTxt.size() == old_size && revisedTxt.size() == new_size)
|
||||
|| (old_size == 0 && new_size == 0 && originalTxt.size() == this.old_ln
|
||||
&& revisedTxt.size() == this.new_ln)) {
|
||||
finalizeChunk();
|
||||
break;
|
||||
}
|
||||
}
|
||||
line = READER.readLine();
|
||||
}
|
||||
if (line == null || line.startsWith("--")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (READER.ready()) {
|
||||
String tailTxt = "";
|
||||
while (READER.ready()) {
|
||||
if (tailTxt.length() > 0) {
|
||||
tailTxt += "\n";
|
||||
}
|
||||
tailTxt += READER.readLine();
|
||||
}
|
||||
data.setTailTxt(tailTxt);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static String[] parseFileNames(String line) {
|
||||
String[] split = line.split(" ");
|
||||
return new String[]{
|
||||
split[2].replaceAll("^a/", ""),
|
||||
split[3].replaceAll("^b/", "")
|
||||
};
|
||||
}
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(UnifiedDiffReader.class.getName());
|
||||
|
||||
public static UnifiedDiff parseUnifiedDiff(InputStream stream) throws IOException, UnifiedDiffParserException {
|
||||
UnifiedDiffReader parser = new UnifiedDiffReader(new BufferedReader(new InputStreamReader(stream)));
|
||||
return parser.parse();
|
||||
}
|
||||
|
||||
private boolean processLine(String line, UnifiedDiffLine... rules) throws UnifiedDiffParserException {
|
||||
if (line == null) {
|
||||
return false;
|
||||
}
|
||||
for (UnifiedDiffLine rule : rules) {
|
||||
if (rule.processLine(line)) {
|
||||
LOG.fine(" >>> processed rule " + rule.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG.warning(" >>> no rule matched " + line);
|
||||
return false;
|
||||
//throw new UnifiedDiffParserException("parsing error at line " + line);
|
||||
}
|
||||
|
||||
private void initFileIfNecessary() {
|
||||
if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
actualFile = null;
|
||||
if (actualFile == null) {
|
||||
actualFile = new UnifiedDiffFile();
|
||||
data.addFile(actualFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void processDiff(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
LOG.log(Level.FINE, "start {0}", line);
|
||||
String[] fromTo = parseFileNames(READER.lastLine());
|
||||
actualFile.setFromFile(fromTo[0]);
|
||||
actualFile.setToFile(fromTo[1]);
|
||||
actualFile.setDiffCommand(line);
|
||||
}
|
||||
|
||||
private List<String> originalTxt = new ArrayList<>();
|
||||
private List<String> revisedTxt = new ArrayList<>();
|
||||
private int old_ln;
|
||||
private int old_size;
|
||||
private int new_ln;
|
||||
private int new_size;
|
||||
|
||||
private void finalizeChunk() {
|
||||
if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) {
|
||||
actualFile.getPatch().addDelta(new ChangeDelta<>(new Chunk<>(
|
||||
old_ln - 1, originalTxt), new Chunk<>(
|
||||
new_ln - 1, revisedTxt)));
|
||||
old_ln = 0;
|
||||
new_ln = 0;
|
||||
originalTxt.clear();
|
||||
revisedTxt.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void processNormalLine(MatchResult match, String line) {
|
||||
String cline = line.substring(1);
|
||||
originalTxt.add(cline);
|
||||
revisedTxt.add(cline);
|
||||
}
|
||||
|
||||
private void processAddLine(MatchResult match, String line) {
|
||||
String cline = line.substring(1);
|
||||
revisedTxt.add(cline);
|
||||
}
|
||||
|
||||
private void processDelLine(MatchResult match, String line) {
|
||||
String cline = line.substring(1);
|
||||
originalTxt.add(cline);
|
||||
}
|
||||
|
||||
private void processChunk(MatchResult match, String chunkStart) {
|
||||
// finalizeChunk();
|
||||
old_ln = toInteger(match, 1, 1);
|
||||
old_size = toInteger(match, 2, 0);
|
||||
new_ln = toInteger(match, 3, 1);
|
||||
new_size = toInteger(match, 4, 0);
|
||||
if (old_ln == 0) {
|
||||
old_ln = 1;
|
||||
}
|
||||
if (new_ln == 0) {
|
||||
new_ln = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static Integer toInteger(MatchResult match, int group, int defValue) throws NumberFormatException {
|
||||
return Integer.valueOf(Objects.toString(match.group(group), "" + defValue));
|
||||
}
|
||||
|
||||
private void processIndex(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
LOG.log(Level.FINE, "index {0}", line);
|
||||
actualFile.setIndex(line.substring(6));
|
||||
}
|
||||
|
||||
private void processFromFile(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
actualFile.setFromFile(extractFileName(line));
|
||||
actualFile.setFromTimestamp(extractTimestamp(line));
|
||||
}
|
||||
|
||||
private void processToFile(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
actualFile.setToFile(extractFileName(line));
|
||||
actualFile.setToTimestamp(extractTimestamp(line));
|
||||
}
|
||||
|
||||
private void processNewFileMode(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
actualFile.setNewFileMode(match.group(1));
|
||||
}
|
||||
|
||||
private void processDeletedFileMode(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
actualFile.setDeletedFileMode(match.group(1));
|
||||
}
|
||||
|
||||
private String extractFileName(String _line) {
|
||||
Matcher matcher = TIMESTAMP_REGEXP.matcher(_line);
|
||||
String line = _line;
|
||||
if (matcher.find()) {
|
||||
line = line.substring(0, matcher.start());
|
||||
}
|
||||
line = line.split("\t")[0];
|
||||
return line.substring(4).replaceFirst("^(a|b|old|new)(\\/)?", "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
private String extractTimestamp(String line) {
|
||||
Matcher matcher = TIMESTAMP_REGEXP.matcher(line);
|
||||
if (matcher.find()) {
|
||||
return matcher.group();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final class UnifiedDiffLine {
|
||||
|
||||
private final Pattern pattern;
|
||||
private final BiConsumer<MatchResult, String> command;
|
||||
private final boolean stopsHeaderParsing;
|
||||
|
||||
public UnifiedDiffLine(String pattern, BiConsumer<MatchResult, String> command) {
|
||||
this(false, pattern, command);
|
||||
}
|
||||
|
||||
public UnifiedDiffLine(boolean stopsHeaderParsing, String pattern, BiConsumer<MatchResult, String> command) {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
this.command = command;
|
||||
this.stopsHeaderParsing = stopsHeaderParsing;
|
||||
}
|
||||
|
||||
public UnifiedDiffLine(boolean stopsHeaderParsing, Pattern pattern, BiConsumer<MatchResult, String> command) {
|
||||
this.pattern = pattern;
|
||||
this.command = command;
|
||||
this.stopsHeaderParsing = stopsHeaderParsing;
|
||||
}
|
||||
|
||||
public boolean validLine(String line) {
|
||||
Matcher m = pattern.matcher(line);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
public boolean processLine(String line) throws UnifiedDiffParserException {
|
||||
Matcher m = pattern.matcher(line);
|
||||
if (m.find()) {
|
||||
command.accept(m.toMatchResult(), line);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStopsHeaderParsing() {
|
||||
return stopsHeaderParsing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UnifiedDiffLine{" + "pattern=" + pattern + ", stopsHeaderParsing=" + stopsHeaderParsing + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InternalUnifiedDiffReader extends BufferedReader {
|
||||
|
||||
private String lastLine;
|
||||
|
||||
public InternalUnifiedDiffReader(Reader reader) {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLine() throws IOException {
|
||||
lastLine = super.readLine();
|
||||
return lastLine();
|
||||
}
|
||||
|
||||
String lastLine() {
|
||||
return lastLine;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @todo use an instance to store contextSize and originalLinesProvider.
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public class UnifiedDiffWriter {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(UnifiedDiffWriter.class.getName());
|
||||
|
||||
public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Writer writer, int contextSize) throws IOException {
|
||||
Objects.requireNonNull(originalLinesProvider, "original lines provider needs to be specified");
|
||||
write(diff, originalLinesProvider, line -> {
|
||||
try {
|
||||
writer.append(line).append("\n");
|
||||
} catch (IOException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}, contextSize);
|
||||
}
|
||||
|
||||
public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Consumer<String> writer, int contextSize) throws IOException {
|
||||
if (diff.getHeader() != null) {
|
||||
writer.accept(diff.getHeader());
|
||||
}
|
||||
|
||||
for (UnifiedDiffFile file : diff.getFiles()) {
|
||||
List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
|
||||
file.getPatch().getDeltas());
|
||||
if (!patchDeltas.isEmpty()) {
|
||||
writeOrNothing(writer, file.getDiffCommand());
|
||||
if (file.getIndex() != null) {
|
||||
writer.accept("index " + file.getIndex());
|
||||
}
|
||||
|
||||
writer.accept("--- " + (file.getFromFile() == null ? "/dev/null" : file.getFromFile()));
|
||||
|
||||
if (file.getToFile() != null) {
|
||||
writer.accept("+++ " + file.getToFile());
|
||||
}
|
||||
|
||||
List<String> originalLines = originalLinesProvider.apply(file.getFromFile());
|
||||
|
||||
List<AbstractDelta<String>> deltas = new ArrayList<>();
|
||||
|
||||
AbstractDelta<String> delta = patchDeltas.get(0);
|
||||
deltas.add(delta); // add the first Delta to the current set
|
||||
// if there's more than 1 Delta, we may need to output them together
|
||||
if (patchDeltas.size() > 1) {
|
||||
for (int i = 1; i < patchDeltas.size(); i++) {
|
||||
int position = delta.getSource().getPosition();
|
||||
|
||||
// Check if the next Delta is too close to the current
|
||||
// position.
|
||||
// And if it is, add it to the current set
|
||||
AbstractDelta<String> nextDelta = patchDeltas.get(i);
|
||||
if ((position + delta.getSource().size() + contextSize) >= (nextDelta
|
||||
.getSource().getPosition() - contextSize)) {
|
||||
deltas.add(nextDelta);
|
||||
} else {
|
||||
// if it isn't, output the current set,
|
||||
// then create a new set and add the current Delta to
|
||||
// it.
|
||||
processDeltas(writer, originalLines, deltas, contextSize, false);
|
||||
deltas.clear();
|
||||
deltas.add(nextDelta);
|
||||
}
|
||||
delta = nextDelta;
|
||||
}
|
||||
|
||||
}
|
||||
// don't forget to process the last set of Deltas
|
||||
processDeltas(writer, originalLines, deltas, contextSize,
|
||||
patchDeltas.size() == 1 && file.getFromFile() == null);
|
||||
}
|
||||
|
||||
}
|
||||
if (diff.getTail() != null) {
|
||||
writer.accept("--");
|
||||
writer.accept(diff.getTail());
|
||||
}
|
||||
}
|
||||
|
||||
private static void processDeltas(Consumer<String> writer,
|
||||
List<String> origLines, List<AbstractDelta<String>> deltas,
|
||||
int contextSize, boolean newFile) {
|
||||
List<String> buffer = new ArrayList<>();
|
||||
int origTotal = 0; // counter for total lines output from Original
|
||||
int revTotal = 0; // counter for total lines output from Original
|
||||
int line;
|
||||
|
||||
AbstractDelta<String> curDelta = deltas.get(0);
|
||||
|
||||
int origStart;
|
||||
if (newFile) {
|
||||
origStart = 0;
|
||||
} else {
|
||||
// NOTE: +1 to overcome the 0-offset Position
|
||||
origStart = curDelta.getSource().getPosition() + 1 - contextSize;
|
||||
if (origStart < 1) {
|
||||
origStart = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
|
||||
if (revStart < 1) {
|
||||
revStart = 1;
|
||||
}
|
||||
|
||||
// find the start of the wrapper context code
|
||||
int contextStart = curDelta.getSource().getPosition() - contextSize;
|
||||
if (contextStart < 0) {
|
||||
contextStart = 0; // clamp to the start of the file
|
||||
}
|
||||
|
||||
// output the context before the first Delta
|
||||
for (line = contextStart; line < curDelta.getSource().getPosition()
|
||||
&& line < origLines.size(); line++) { //
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
}
|
||||
// output the first Delta
|
||||
getDeltaText(txt -> buffer.add(txt), curDelta);
|
||||
origTotal += curDelta.getSource().getLines().size();
|
||||
revTotal += curDelta.getTarget().getLines().size();
|
||||
|
||||
int deltaIndex = 1;
|
||||
while (deltaIndex < deltas.size()) { // for each of the other Deltas
|
||||
AbstractDelta<String> nextDelta = deltas.get(deltaIndex);
|
||||
int intermediateStart = curDelta.getSource().getPosition()
|
||||
+ curDelta.getSource().getLines().size();
|
||||
for (line = intermediateStart; line < nextDelta.getSource().getPosition()
|
||||
&& line < origLines.size(); line++) {
|
||||
// output the code between the last Delta and this one
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
}
|
||||
getDeltaText(txt -> buffer.add(txt), nextDelta); // output the Delta
|
||||
origTotal += nextDelta.getSource().getLines().size();
|
||||
revTotal += nextDelta.getTarget().getLines().size();
|
||||
curDelta = nextDelta;
|
||||
deltaIndex++;
|
||||
}
|
||||
|
||||
// Now output the post-Delta context code, clamping the end of the file
|
||||
contextStart = curDelta.getSource().getPosition()
|
||||
+ curDelta.getSource().getLines().size();
|
||||
for (line = contextStart; (line < (contextStart + contextSize))
|
||||
&& (line < origLines.size()); line++) {
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
}
|
||||
|
||||
// Create and insert the block header, conforming to the Unified Diff
|
||||
// standard
|
||||
writer.accept("@@ -" + origStart + "," + origTotal + " +" + revStart + "," + revTotal + " @@");
|
||||
buffer.forEach(txt -> {
|
||||
writer.accept(txt);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter
|
||||
*
|
||||
* @param delta - the Delta to output
|
||||
* @return list of String lines of code.
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static void getDeltaText(Consumer<String> writer, AbstractDelta<String> delta) {
|
||||
for (String line : delta.getSource().getLines()) {
|
||||
writer.accept("-" + line);
|
||||
}
|
||||
for (String line : delta.getTarget().getLines()) {
|
||||
writer.accept("+" + line);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeOrNothing(Consumer<String> writer, String str) throws IOException {
|
||||
if (str != null) {
|
||||
writer.accept(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* This is the first test version of a multifile diff parser. The Api is still subject
|
||||
* of change.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.github.difflib;
|
||||
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.DeleteDelta;
|
||||
import com.github.difflib.patch.Delta;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.EqualDelta;
|
||||
import com.github.difflib.patch.InsertDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.io.BufferedReader;
|
||||
@@ -19,99 +19,100 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import java.util.zip.ZipFile;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class DiffUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testDiff_Insert() throws DiffException {
|
||||
public void testDiff_Insert() {
|
||||
final Patch<String> patch = DiffUtils.diff(Arrays.asList("hhh"), Arrays.
|
||||
asList("hhh", "jjj", "kkk"));
|
||||
assertNotNull(patch);
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
final Delta<String> delta = patch.getDeltas().get(0);
|
||||
final AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof InsertDelta);
|
||||
assertEquals(new Chunk<>(1, Collections.<String>emptyList()), delta.getOriginal());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("jjj", "kkk")), delta.getRevised());
|
||||
assertEquals(new Chunk<>(1, Collections.<String>emptyList()), delta.getSource());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("jjj", "kkk")), delta.getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_Delete() throws DiffException {
|
||||
public void testDiff_Delete() {
|
||||
final Patch<String> patch = DiffUtils.diff(Arrays.asList("ddd", "fff", "ggg"), Arrays.
|
||||
asList("ggg"));
|
||||
assertNotNull(patch);
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
final Delta<String> delta = patch.getDeltas().get(0);
|
||||
final AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof DeleteDelta);
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("ddd", "fff")), delta.getOriginal());
|
||||
assertEquals(new Chunk<>(0, Collections.<String>emptyList()), delta.getRevised());
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("ddd", "fff")), delta.getSource());
|
||||
assertEquals(new Chunk<>(0, Collections.<String>emptyList()), delta.getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_Change() throws DiffException {
|
||||
public void testDiff_Change() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "zzz", "ccc");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
assertNotNull(patch);
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
final Delta<String> delta = patch.getDeltas().get(0);
|
||||
final AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof ChangeDelta);
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("bbb")), delta.getOriginal());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("zzz")), delta.getRevised());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("bbb")), delta.getSource());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("zzz")), delta.getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_EmptyList() throws DiffException {
|
||||
public void testDiff_EmptyList() {
|
||||
final Patch<String> patch = DiffUtils.diff(new ArrayList<>(), new ArrayList<>());
|
||||
assertNotNull(patch);
|
||||
assertEquals(0, patch.getDeltas().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_EmptyListWithNonEmpty() throws DiffException {
|
||||
public void testDiff_EmptyListWithNonEmpty() {
|
||||
final Patch<String> patch = DiffUtils.diff(new ArrayList<>(), Arrays.asList("aaa"));
|
||||
assertNotNull(patch);
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
final Delta<String> delta = patch.getDeltas().get(0);
|
||||
final AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof InsertDelta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffInline() throws DiffException {
|
||||
public void testDiffInline() {
|
||||
final Patch<String> patch = DiffUtils.diffInline("", "test");
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
assertTrue(patch.getDeltas().get(0) instanceof InsertDelta);
|
||||
assertEquals(0, patch.getDeltas().get(0).getOriginal().getPosition());
|
||||
assertEquals(0, patch.getDeltas().get(0).getOriginal().getLines().size());
|
||||
assertEquals("test", patch.getDeltas().get(0).getRevised().getLines().get(0));
|
||||
assertEquals(0, patch.getDeltas().get(0).getSource().getPosition());
|
||||
assertEquals(0, patch.getDeltas().get(0).getSource().getLines().size());
|
||||
assertEquals("test", patch.getDeltas().get(0).getTarget().getLines().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffInline2() throws DiffException {
|
||||
public void testDiffInline2() {
|
||||
final Patch<String> patch = DiffUtils.diffInline("es", "fest");
|
||||
assertEquals(2, patch.getDeltas().size());
|
||||
assertTrue(patch.getDeltas().get(0) instanceof InsertDelta);
|
||||
assertEquals(0, patch.getDeltas().get(0).getOriginal().getPosition());
|
||||
assertEquals(2, patch.getDeltas().get(1).getOriginal().getPosition());
|
||||
assertEquals(0, patch.getDeltas().get(0).getOriginal().getLines().size());
|
||||
assertEquals(0, patch.getDeltas().get(1).getOriginal().getLines().size());
|
||||
assertEquals("f", patch.getDeltas().get(0).getRevised().getLines().get(0));
|
||||
assertEquals("t", patch.getDeltas().get(1).getRevised().getLines().get(0));
|
||||
assertEquals(0, patch.getDeltas().get(0).getSource().getPosition());
|
||||
assertEquals(2, patch.getDeltas().get(1).getSource().getPosition());
|
||||
assertEquals(0, patch.getDeltas().get(0).getSource().getLines().size());
|
||||
assertEquals(0, patch.getDeltas().get(1).getSource().getLines().size());
|
||||
assertEquals("f", patch.getDeltas().get(0).getTarget().getLines().get(0));
|
||||
assertEquals("t", patch.getDeltas().get(1).getTarget().getLines().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffIntegerList() throws DiffException {
|
||||
public void testDiffIntegerList() {
|
||||
List<Integer> original = Arrays.asList(1, 2, 3, 4, 5);
|
||||
List<Integer> revised = Arrays.asList(2, 3, 4, 6);
|
||||
|
||||
final Patch<Integer> patch = DiffUtils.diff(original, revised);
|
||||
|
||||
for (Delta delta : patch.getDeltas()) {
|
||||
for (AbstractDelta delta : patch.getDeltas()) {
|
||||
System.out.println(delta);
|
||||
}
|
||||
|
||||
@@ -121,7 +122,7 @@ public class DiffUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffMissesChangeForkDnaumenkoIssue31() throws DiffException {
|
||||
public void testDiffMissesChangeForkDnaumenkoIssue31() {
|
||||
List<String> original = Arrays.asList("line1", "line2", "line3");
|
||||
List<String> revised = Arrays.asList("line1", "line2-2", "line4");
|
||||
|
||||
@@ -134,8 +135,8 @@ public class DiffUtilsTest {
|
||||
* To test this, the greedy meyer algorithm is not suitable.
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException, DiffException {
|
||||
@Disabled
|
||||
public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException {
|
||||
ZipFile zip = new ZipFile(TestConstants.MOCK_FOLDER + "/large_dataset1.zip");
|
||||
|
||||
Patch<String> patch = DiffUtils.diff(
|
||||
@@ -154,10 +155,76 @@ public class DiffUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1() throws DiffException {
|
||||
public void testDiffMyersExample1() {
|
||||
final Patch<String> patch = DiffUtils.diff(Arrays.asList("A", "B", "C", "A", "B", "B", "A"), Arrays.asList("C", "B", "A", "B", "A", "C"));
|
||||
assertNotNull(patch);
|
||||
assertEquals(4, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [InsertDelta, position: 3, lines: [B]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_Equal() {
|
||||
final Patch<String> patch = DiffUtils.diff(
|
||||
Arrays.asList("hhh", "jjj", "kkk"),
|
||||
Arrays.asList("hhh", "jjj", "kkk"), true);
|
||||
assertNotNull(patch);
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
final AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof EqualDelta);
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("hhh", "jjj", "kkk")), delta.getSource());
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("hhh", "jjj", "kkk")), delta.getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_InsertWithEqual() {
|
||||
final Patch<String> patch = DiffUtils.diff(Arrays.asList("hhh"), Arrays.
|
||||
asList("hhh", "jjj", "kkk"), true);
|
||||
assertNotNull(patch);
|
||||
assertEquals(2, patch.getDeltas().size());
|
||||
|
||||
AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof EqualDelta);
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("hhh")), delta.getSource());
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("hhh")), delta.getTarget());
|
||||
|
||||
delta = patch.getDeltas().get(1);
|
||||
assertTrue(delta instanceof InsertDelta);
|
||||
assertEquals(new Chunk<>(1, Collections.<String>emptyList()), delta.getSource());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("jjj", "kkk")), delta.getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_ProblemIssue42() {
|
||||
final Patch<String> patch = DiffUtils.diff(
|
||||
Arrays.asList("The", "dog", "is", "brown"),
|
||||
Arrays.asList("The", "fox", "is", "down"), true);
|
||||
|
||||
System.out.println(patch);
|
||||
assertNotNull(patch);
|
||||
assertEquals(4, patch.getDeltas().size());
|
||||
|
||||
|
||||
assertThat(patch.getDeltas()).extracting(d -> d.getType().name())
|
||||
.containsExactly("EQUAL", "CHANGE", "EQUAL", "CHANGE");
|
||||
|
||||
AbstractDelta<String> delta = patch.getDeltas().get(0);
|
||||
assertTrue(delta instanceof EqualDelta);
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("The")), delta.getSource());
|
||||
assertEquals(new Chunk<>(0, Arrays.asList("The")), delta.getTarget());
|
||||
|
||||
delta = patch.getDeltas().get(1);
|
||||
assertTrue(delta instanceof ChangeDelta);
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("dog")), delta.getSource());
|
||||
assertEquals(new Chunk<>(1, Arrays.asList("fox")), delta.getTarget());
|
||||
|
||||
delta = patch.getDeltas().get(2);
|
||||
assertTrue(delta instanceof EqualDelta);
|
||||
assertEquals(new Chunk<>(2, Arrays.asList("is")), delta.getSource());
|
||||
assertEquals(new Chunk<>(2, Arrays.asList("is")), delta.getTarget());
|
||||
|
||||
delta = patch.getDeltas().get(3);
|
||||
assertTrue(delta instanceof ChangeDelta);
|
||||
assertEquals(new Chunk<>(3, Arrays.asList("brown")), delta.getSource());
|
||||
assertEquals(new Chunk<>(3, Arrays.asList("down")), delta.getTarget());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package com.github.difflib;
|
||||
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class GenerateUnifiedDiffTest {
|
||||
|
||||
public static List<String> fileToLines(String filename) throws FileNotFoundException, IOException {
|
||||
List<String> lines = new ArrayList<>();
|
||||
String line = "";
|
||||
try (BufferedReader in = new BufferedReader(new FileReader(filename))) {
|
||||
while ((line = in.readLine()) != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateUnified() throws IOException {
|
||||
List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "original.txt");
|
||||
List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "revised.txt");
|
||||
|
||||
verify(origLines, revLines, "original.txt", "revised.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateUnifiedWithOneDelta() throws IOException {
|
||||
List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_original.txt");
|
||||
List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_revised.txt");
|
||||
|
||||
verify(origLines, revLines, "one_delta_test_original.txt", "one_delta_test_revised.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateUnifiedDiffWithoutAnyDeltas() {
|
||||
List<String> test = Arrays.asList("abc");
|
||||
Patch<String> patch = DiffUtils.diff(test, test);
|
||||
UnifiedDiffUtils.generateUnifiedDiff("abc", "abc", test, patch, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_Issue10() throws IOException {
|
||||
final List<String> baseLines = fileToLines(TestConstants.MOCK_FOLDER + "issue10_base.txt");
|
||||
final List<String> patchLines = fileToLines(TestConstants.MOCK_FOLDER + "issue10_patch.txt");
|
||||
final Patch<String> p = UnifiedDiffUtils.parseUnifiedDiff(patchLines);
|
||||
try {
|
||||
DiffUtils.patch(baseLines, p);
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue 12
|
||||
*/
|
||||
@Test
|
||||
public void testPatchWithNoDeltas() throws IOException {
|
||||
final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_1.txt");
|
||||
final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_2.txt");
|
||||
verify(lines1, lines2, "issue11_1.txt", "issue11_2.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff5() throws IOException {
|
||||
final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "5A.txt");
|
||||
final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "5B.txt");
|
||||
verify(lines1, lines2, "5A.txt", "5B.txt");
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue 19
|
||||
*/
|
||||
@Test
|
||||
public void testDiffWithHeaderLineInText() {
|
||||
List<String> original = new ArrayList<>();
|
||||
List<String> revised = new ArrayList<>();
|
||||
|
||||
original.add("test line1");
|
||||
original.add("test line2");
|
||||
original.add("test line 4");
|
||||
original.add("test line 5");
|
||||
|
||||
revised.add("test line1");
|
||||
revised.add("test line2");
|
||||
revised.add("@@ -2,6 +2,7 @@");
|
||||
revised.add("test line 4");
|
||||
revised.add("test line 5");
|
||||
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
List<String> udiff = UnifiedDiffUtils.generateUnifiedDiff("original", "revised",
|
||||
original, patch, 10);
|
||||
UnifiedDiffUtils.parseUnifiedDiff(udiff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue 47
|
||||
*/
|
||||
@Test
|
||||
public void testNewFileCreation() {
|
||||
List<String> original = new ArrayList<>();
|
||||
List<String> revised = new ArrayList<>();
|
||||
|
||||
revised.add("line1");
|
||||
revised.add("line2");
|
||||
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
List<String> udiff = UnifiedDiffUtils.generateUnifiedDiff(null, "revised",
|
||||
original, patch, 10);
|
||||
|
||||
assertEquals("--- /dev/null", udiff.get(0));
|
||||
assertEquals("+++ revised", udiff.get(1));
|
||||
assertEquals("@@ -0,0 +1,2 @@", udiff.get(2));
|
||||
|
||||
UnifiedDiffUtils.parseUnifiedDiff(udiff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue 89
|
||||
*/
|
||||
@Test
|
||||
public void testChagngePosition() throws IOException {
|
||||
final List<String> patchLines = fileToLines(TestConstants.MOCK_FOLDER + "issue89_patch.txt");
|
||||
final Patch<String> patch = UnifiedDiffUtils.parseUnifiedDiff(patchLines);
|
||||
List<Integer> realRemoveListOne = Collections.singletonList(3);
|
||||
List<Integer> realAddListOne = Arrays.asList(3, 7, 8, 9, 10, 11, 12, 13, 14);
|
||||
validateChangePosition(patch, 0, realRemoveListOne, realAddListOne);
|
||||
List<Integer> realRemoveListTwo = new ArrayList<>();
|
||||
List<Integer> realAddListTwo = Arrays.asList(27, 28);
|
||||
validateChangePosition(patch, 1, realRemoveListTwo, realAddListTwo);
|
||||
|
||||
}
|
||||
|
||||
private void validateChangePosition(Patch<String> patch, int index, List<Integer> realRemoveList,
|
||||
List<Integer> realAddList ) {
|
||||
final Chunk originChunk = patch.getDeltas().get(index).getSource();
|
||||
List<Integer> removeList = originChunk.getChangePosition();
|
||||
assertEquals(realRemoveList.size(), removeList.size());
|
||||
for (Integer ele: realRemoveList) {
|
||||
assertTrue(realRemoveList.contains(ele));
|
||||
}
|
||||
for (Integer ele: removeList) {
|
||||
assertTrue(realAddList.contains(ele));
|
||||
}
|
||||
final Chunk targetChunk = patch.getDeltas().get(index).getTarget();
|
||||
List<Integer> addList = targetChunk.getChangePosition();
|
||||
assertEquals(realAddList.size(), addList.size());
|
||||
for (Integer ele: realAddList) {
|
||||
assertTrue(addList.contains(ele));
|
||||
}
|
||||
for (Integer ele: addList) {
|
||||
assertTrue(realAddList.contains(ele));
|
||||
}
|
||||
}
|
||||
|
||||
private void verify(List<String> origLines, List<String> revLines,
|
||||
String originalFile, String revisedFile) {
|
||||
Patch<String> patch = DiffUtils.diff(origLines, revLines);
|
||||
List<String> unifiedDiff = UnifiedDiffUtils.generateUnifiedDiff(originalFile, revisedFile,
|
||||
origLines, patch, 10);
|
||||
|
||||
System.out.println(unifiedDiff.stream().collect(joining("\n")));
|
||||
|
||||
Patch<String> fromUnifiedPatch = UnifiedDiffUtils.parseUnifiedDiff(unifiedDiff);
|
||||
List<String> patchedLines;
|
||||
try {
|
||||
patchedLines = fromUnifiedPatch.applyTo(origLines);
|
||||
assertEquals(revLines.size(), patchedLines.size());
|
||||
for (int i = 0; i < revLines.size(); i++) {
|
||||
String l1 = revLines.get(i);
|
||||
String l2 = patchedLines.get(i);
|
||||
if (!l1.equals(l2)) {
|
||||
fail("Line " + (i + 1) + " of the patched file did not match the revised original");
|
||||
}
|
||||
}
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ public final class TestConstants {
|
||||
|
||||
public static final String BASE_FOLDER_RESOURCES = "target/test-classes/";
|
||||
/**
|
||||
* The base folder containing the test files. Ends with {@link #FS}.
|
||||
* The base folder containing the test files.
|
||||
*/
|
||||
public static final String MOCK_FOLDER = BASE_FOLDER_RESOURCES + "/mocks/";
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class MyersDiffTest {
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1Forward() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(original, revised, new MyersDiff<String>().computeDiff(original, revised, null));
|
||||
assertNotNull(patch);
|
||||
assertEquals(4, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [InsertDelta, position: 3, lines: [B]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1ForwardWithListener() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
|
||||
List<String> logdata = new ArrayList<>();
|
||||
final Patch<String> patch = Patch.generate(original, revised,
|
||||
new MyersDiff<String>().computeDiff(original, revised, new DiffAlgorithmListener() {
|
||||
@Override
|
||||
public void diffStart() {
|
||||
logdata.add("start");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffStep(int value, int max) {
|
||||
logdata.add(value + " - " + max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffEnd() {
|
||||
logdata.add("end");
|
||||
}
|
||||
}));
|
||||
assertNotNull(patch);
|
||||
assertEquals(4, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [InsertDelta, position: 3, lines: [B]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
System.out.println(logdata);
|
||||
assertEquals(8, logdata.size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,8 +2,7 @@ package com.github.difflib.examples;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.TestConstants;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.Delta;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -15,14 +14,14 @@ public class ComputeDifference {
|
||||
private static final String ORIGINAL = TestConstants.MOCK_FOLDER + "original.txt";
|
||||
private static final String RIVISED = TestConstants.MOCK_FOLDER + "revised.txt";
|
||||
|
||||
public static void main(String[] args) throws DiffException, IOException {
|
||||
public static void main(String[] args) throws IOException {
|
||||
List<String> original = Files.readAllLines(new File(ORIGINAL).toPath());
|
||||
List<String> revised = Files.readAllLines(new File(RIVISED).toPath());
|
||||
|
||||
// Compute diff. Get the Patch object. Patch is the container for computed deltas.
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
|
||||
for (Delta<String> delta : patch.getDeltas()) {
|
||||
for (AbstractDelta<String> delta : patch.getDeltas()) {
|
||||
System.out.println(delta);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class PatchTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Insert() throws DiffException {
|
||||
public void testPatch_Insert() {
|
||||
final List<String> insertTest_from = Arrays.asList("hhh");
|
||||
final List<String> insertTest_to = Arrays.asList("hhh", "jjj", "kkk", "lll");
|
||||
|
||||
@@ -24,7 +23,7 @@ public class PatchTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Delete() throws DiffException {
|
||||
public void testPatch_Delete() {
|
||||
final List<String> deleteTest_from = Arrays.asList("ddd", "fff", "ggg", "hhh");
|
||||
final List<String> deleteTest_to = Arrays.asList("ggg");
|
||||
|
||||
@@ -37,7 +36,7 @@ public class PatchTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change() throws DiffException {
|
||||
public void testPatch_Change() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
@@ -0,0 +1,624 @@
|
||||
package com.github.difflib.text;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class DiffRowGeneratorTest {
|
||||
|
||||
@Test
|
||||
public void testGenerator_Default() {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(Integer.MAX_VALUE) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of normalize method, of class StringUtils.
|
||||
*/
|
||||
@Test
|
||||
public void testNormalize_List() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.build();
|
||||
assertEquals(Collections.singletonList(" test"), generator.normalizeLines(Collections.singletonList("\ttest")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerator_Default2() {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(0) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerator_InlineDiff() {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.columnWidth(Integer.MAX_VALUE) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertTrue(rows.get(0).getOldLine().indexOf("<span") > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerator_IgnoreWhitespaces() {
|
||||
String first = "anything \n \nother\nmore lines";
|
||||
String second = "anything\n\nother\nsome more lines";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.ignoreWhiteSpaces(true)
|
||||
.columnWidth(Integer.MAX_VALUE) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(4, rows.size());
|
||||
assertEquals(rows.get(0).getTag(), DiffRow.Tag.EQUAL);
|
||||
assertEquals(rows.get(1).getTag(), DiffRow.Tag.EQUAL);
|
||||
assertEquals(rows.get(2).getTag(), DiffRow.Tag.EQUAL);
|
||||
assertEquals(rows.get(3).getTag(), DiffRow.Tag.CHANGE);
|
||||
}
|
||||
|
||||
private List<String> split(String content) {
|
||||
return Arrays.asList(content.split("\n"));
|
||||
}
|
||||
|
||||
private void print(List<DiffRow> diffRows) {
|
||||
for (DiffRow row : diffRows) {
|
||||
System.out.println(row);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithWordWrap() {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(5)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("[CHANGE,anyth<br/>ing ,anyth<br/>ing]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE, ,]", rows.get(1).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(2).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMerge() {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("[CHANGE,anything<span class=\"editOldInline\"> </span>,anything]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\"> </span>,]", rows.get(1).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(2).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMerge2() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"), Arrays.asList("ester"));
|
||||
print(rows);
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">T</span>est<span class=\"editNewInline\">er</span>,ester]", rows.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMerge3() {
|
||||
String first = "test\nanything \n \nother";
|
||||
String second = "anything\n\nother\ntest\ntest2";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(6, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">test</span>,anything]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE,anything<span class=\"editOldInline\"> </span>,]", rows.get(1).toString());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\"> </span>,]", rows.get(2).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(3).toString());
|
||||
assertEquals("[INSERT,<span class=\"editNewInline\">test</span>,test]", rows.get(4).toString());
|
||||
assertEquals("[INSERT,<span class=\"editNewInline\">test2</span>,test2]", rows.get(5).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMergeByWord4() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"), Arrays.asList("ester"));
|
||||
print(rows);
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">Test</span><span class=\"editNewInline\">ester</span>,ester]", rows.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMergeByWord5() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.columnWidth(80)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test feature"), Arrays.asList("ester feature best"));
|
||||
print(rows);
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">Test</span><span class=\"editNewInline\">ester</span> <br/>feature<span class=\"editNewInline\"> best</span>,ester feature best]", rows.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitString() {
|
||||
List<String> list = DiffRowGenerator.splitStringPreserveDelimiter("test,test2", DiffRowGenerator.SPLIT_BY_WORD_PATTERN);
|
||||
assertEquals(3, list.size());
|
||||
assertEquals("[test, ,, test2]", list.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitString2() {
|
||||
List<String> list = DiffRowGenerator.splitStringPreserveDelimiter("test , test2", DiffRowGenerator.SPLIT_BY_WORD_PATTERN);
|
||||
System.out.println(list);
|
||||
assertEquals(5, list.size());
|
||||
assertEquals("[test, , ,, , test2]", list.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitString3() {
|
||||
List<String> list = DiffRowGenerator.splitStringPreserveDelimiter("test,test2,", DiffRowGenerator.SPLIT_BY_WORD_PATTERN);
|
||||
System.out.println(list);
|
||||
assertEquals(4, list.size());
|
||||
assertEquals("[test, ,, test2, ,]", list.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorExample1() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test senctence."),
|
||||
Arrays.asList("This is a test for diffutils."));
|
||||
|
||||
System.out.println(rows.get(0).getOldLine());
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("This is a test ~senctence~**for diffutils**.", rows.get(0).getOldLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorExample2() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test senctence.", "This is the second line.", "And here is the finish."),
|
||||
Arrays.asList("This is a test for diffutils.", "This is the second line."));
|
||||
|
||||
System.out.println("|original|new|");
|
||||
System.out.println("|--------|---|");
|
||||
for (DiffRow row : rows) {
|
||||
System.out.println("|" + row.getOldLine() + "|" + row.getNewLine() + "|");
|
||||
}
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("This is a test ~senctence~.", rows.get(0).getOldLine());
|
||||
assertEquals("This is a test **for diffutils**.", rows.get(0).getNewLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorUnchanged() {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(5)
|
||||
.reportLinesUnchanged(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("[CHANGE,anything ,anything]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE, ,]", rows.get(1).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(2).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue14() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffBySplitter(line -> DiffRowGenerator.splitStringPreserveDelimiter(line, Pattern.compile(",")))
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("J. G. Feldstein, Chair"),
|
||||
Arrays.asList("T. P. Pastor, Chair"));
|
||||
|
||||
System.out.println(rows.get(0).getOldLine());
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("~J. G. Feldstein~**T. P. Pastor**, Chair", rows.get(0).getOldLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue15() throws IOException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true) //show the ~ ~ and ** ** symbols on each difference
|
||||
.inlineDiffByWord(true) //show the ~ ~ and ** ** around each different word instead of each letter
|
||||
//.reportLinesUnchanged(true) //experiment
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
|
||||
List<String> listOne = Files.lines(new File("target/test-classes/mocks/issue15_1.txt").toPath())
|
||||
.collect(toList());
|
||||
|
||||
List<String> listTwo = Files.lines(new File("target/test-classes/mocks/issue15_2.txt").toPath())
|
||||
.collect(toList());
|
||||
|
||||
List<DiffRow> rows = generator.generateDiffRows(listOne, listTwo);
|
||||
|
||||
assertEquals(9, rows.size());
|
||||
|
||||
for (DiffRow row : rows) {
|
||||
System.out.println("|" + row.getOldLine() + "| " + row.getNewLine() + " |");
|
||||
if (!row.getOldLine().startsWith("TABLE_NAME")) {
|
||||
assertTrue(row.getNewLine().startsWith("**ACTIONS_C16913**"));
|
||||
assertTrue(row.getOldLine().startsWith("~ACTIONS_C1700"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue22() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
String aa = "This is a test senctence.";
|
||||
String bb = "This is a test for diffutils.\nThis is the second line.";
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList(aa.split("\n")),
|
||||
Arrays.asList(bb.split("\n")));
|
||||
|
||||
assertEquals("[[CHANGE,This is a test ~senctence~.,This is a test **for diffutils**.], [CHANGE,,**This is the second line.**]]",
|
||||
rows.toString());
|
||||
|
||||
System.out.println("|original|new|");
|
||||
System.out.println("|--------|---|");
|
||||
for (DiffRow row : rows) {
|
||||
System.out.println("|" + row.getOldLine() + "|" + row.getNewLine() + "|");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue22_2() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
String aa = "This is a test for diffutils.\nThis is the second line.";
|
||||
String bb = "This is a test senctence.";
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList(aa.split("\n")),
|
||||
Arrays.asList(bb.split("\n")));
|
||||
|
||||
assertEquals("[[CHANGE,This is a test ~for diffutils~.,This is a test **senctence**.], [CHANGE,~This is the second line.~,]]",
|
||||
rows.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue22_3() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
String aa = "This is a test senctence.";
|
||||
String bb = "This is a test for diffutils.\nThis is the second line.\nAnd one more.";
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList(aa.split("\n")),
|
||||
Arrays.asList(bb.split("\n")));
|
||||
|
||||
assertEquals("[[CHANGE,This is a test ~senctence~.,This is a test **for diffutils**.], [CHANGE,,**This is the second line.**], [CHANGE,,**And one more.**]]",
|
||||
rows.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue41DefaultNormalizer() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("<"), Arrays.asList("<"));
|
||||
assertEquals("[[EQUAL,<,<]]", rows.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue41UserNormalizer() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.lineNormalizer(str -> str.replace("\t", " "))
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("<"), Arrays.asList("<"));
|
||||
assertEquals("[[EQUAL,<,<]]", rows.toString());
|
||||
rows = generator.generateDiffRows(Arrays.asList("\t<"), Arrays.asList("<"));
|
||||
assertEquals("[[CHANGE, <,<]]", rows.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerationIssue44reportLinesUnchangedProblem() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.reportLinesUnchanged(true)
|
||||
.oldTag(f -> "~~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("<dt>To do</dt>"), Arrays.asList("<dt>Done</dt>"));
|
||||
assertEquals("[[CHANGE,<dt>~~T~~o~~ do~~</dt>,<dt>**D**o**ne**</dt>]]", rows.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreWhitespaceIssue66() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.ignoreWhiteSpaces(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.oldTag(f -> "~") //introduce markdown style for strikethrough
|
||||
.newTag(f -> "**") //introduce markdown style for bold
|
||||
.build();
|
||||
|
||||
//compute the differences for two test texts.
|
||||
//CHECKSTYLE:OFF
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This\tis\ta\ttest."),
|
||||
Arrays.asList("This is a test"));
|
||||
//CHECKSTYLE:ON
|
||||
|
||||
assertEquals("This is a test~.~", rows.get(0).getOldLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreWhitespaceIssue66_2() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.ignoreWhiteSpaces(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.oldTag(f -> "~") //introduce markdown style for strikethrough
|
||||
.newTag(f -> "**") //introduce markdown style for bold
|
||||
.build();
|
||||
|
||||
//compute the differences for two test texts.
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test."),
|
||||
Arrays.asList("This is a test"));
|
||||
|
||||
assertEquals("This is a test~.~", rows.get(0).getOldLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreWhitespaceIssue64() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.ignoreWhiteSpaces(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.oldTag(f -> "~") //introduce markdown style for strikethrough
|
||||
.newTag(f -> "**") //introduce markdown style for bold
|
||||
.build();
|
||||
|
||||
//compute the differences for two test texts.
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("test\n\ntestline".split("\n")),
|
||||
Arrays.asList("A new text line\n\nanother one".split("\n")));
|
||||
|
||||
assertThat(rows).extracting(item -> item.getOldLine())
|
||||
.containsExactly("~test~**A new text line**",
|
||||
"",
|
||||
"~testline~**another one**");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceDiffsIssue63() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.oldTag(f -> "~") //introduce markdown style for strikethrough
|
||||
.newTag(f -> "**") //introduce markdown style for bold
|
||||
.processDiffs(str -> str.replace(" ", "/"))
|
||||
.build();
|
||||
|
||||
//compute the differences for two test texts.
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test."),
|
||||
Arrays.asList("This is a test"));
|
||||
|
||||
assertEquals("This~//~**/**is~//~**/**a~//~**/**test~.~", rows.get(0).getOldLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProblemTooManyDiffRowsIssue65() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.reportLinesUnchanged(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(false)
|
||||
.replaceOriginalLinefeedInChangesWithSpaces(true)
|
||||
.build();
|
||||
|
||||
List<DiffRow> diffRows = generator.generateDiffRows(
|
||||
Arrays.asList("Ich möchte nicht mit einem Bot sprechen.", "Ich soll das schon wieder wiederholen?"),
|
||||
Arrays.asList("Ich möchte nicht mehr mit dir sprechen. Leite mich weiter.", "Kannst du mich zum Kundendienst weiterleiten?"));
|
||||
|
||||
print(diffRows);
|
||||
|
||||
assertThat(diffRows).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProblemTooManyDiffRowsIssue65_NoMerge() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.reportLinesUnchanged(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.mergeOriginalRevised(false)
|
||||
.inlineDiffByWord(false)
|
||||
.build();
|
||||
|
||||
List<DiffRow> diffRows = generator.generateDiffRows(
|
||||
Arrays.asList("Ich möchte nicht mit einem Bot sprechen.", "Ich soll das schon wieder wiederholen?"),
|
||||
Arrays.asList("Ich möchte nicht mehr mit dir sprechen. Leite mich weiter.", "Kannst du mich zum Kundendienst weiterleiten?"));
|
||||
|
||||
System.out.println(diffRows);
|
||||
|
||||
assertThat(diffRows).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProblemTooManyDiffRowsIssue65_DiffByWord() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.reportLinesUnchanged(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.build();
|
||||
|
||||
List<DiffRow> diffRows = generator.generateDiffRows(
|
||||
Arrays.asList("Ich möchte nicht mit einem Bot sprechen.", "Ich soll das schon wieder wiederholen?"),
|
||||
Arrays.asList("Ich möchte nicht mehr mit dir sprechen. Leite mich weiter.", "Kannst du mich zum Kundendienst weiterleiten?"));
|
||||
|
||||
System.out.println(diffRows);
|
||||
|
||||
assertThat(diffRows).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProblemTooManyDiffRowsIssue65_NoInlineDiff() {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(false)
|
||||
.reportLinesUnchanged(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(false)
|
||||
.build();
|
||||
|
||||
List<DiffRow> diffRows = generator.generateDiffRows(
|
||||
Arrays.asList("Ich möchte nicht mit einem Bot sprechen.", "Ich soll das schon wieder wiederholen?"),
|
||||
Arrays.asList("Ich möchte nicht mehr mit dir sprechen. Leite mich weiter.", "Kannst du mich zum Kundendienst weiterleiten?"));
|
||||
|
||||
System.out.println(diffRows);
|
||||
|
||||
assertThat(diffRows).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinefeedInStandardTagsWithLineWidthIssue81() {
|
||||
List<String> original = Arrays.asList(("American bobtail jaguar. American bobtail bombay but turkish angora and tomcat.\n"
|
||||
+ "Russian blue leopard. Lion. Tabby scottish fold for russian blue, so savannah yet lynx. Tomcat singapura, cheetah.\n"
|
||||
+ "Bengal tiger panther but singapura but bombay munchkin for cougar.").split("\n"));
|
||||
List<String> revised = Arrays.asList(("bobtail jaguar. American bobtail turkish angora and tomcat.\n"
|
||||
+ "Russian blue leopard. Lion. Tabby scottish folded for russian blue, so savannah yettie? lynx. Tomcat singapura, cheetah.\n"
|
||||
+ "Bengal tiger panther but singapura but bombay munchkin for cougar. And more.").split("\n"));
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.ignoreWhiteSpaces(true)
|
||||
.columnWidth(100)
|
||||
.build();
|
||||
List<DiffRow> deltas = generator.generateDiffRows(original, revised);
|
||||
|
||||
System.out.println(deltas);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue86WrongInlineDiff() throws IOException {
|
||||
String original = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue_86_original.txt")).collect(joining("\n"));
|
||||
String revised = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue_86_revised.txt")).collect(joining("\n"));
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(false)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag( f -> "~" )
|
||||
.newTag( f -> "**" )
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList(original.split("\n")),
|
||||
Arrays.asList(revised.split("\n")));
|
||||
|
||||
for (DiffRow diff : rows) {
|
||||
System.out.println(diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
package com.github.difflib.text;
|
||||
|
||||
import java.util.Collections;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -41,14 +41,6 @@ public class StringUtilsTest {
|
||||
assertEquals(" test", StringUtils.normalize("\ttest"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of normalize method, of class StringUtils.
|
||||
*/
|
||||
@Test
|
||||
public void testNormalize_List() {
|
||||
assertEquals(Collections.singletonList(" test"), StringUtils.normalize(Collections.singletonList("\ttest")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of wrapText method, of class StringUtils.
|
||||
*/
|
||||
@@ -59,9 +51,10 @@ public class StringUtilsTest {
|
||||
assertEquals("test", StringUtils.wrapText("test", 10));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void testWrapText_String_int_zero() {
|
||||
assertEquals("test", StringUtils.wrapText("test", -1));
|
||||
Assertions.assertThrows(IllegalArgumentException.class,
|
||||
() -> StringUtils.wrapText("test", -1));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public class UnifiedDiffReaderTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleParse() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(UnifiedDiffReaderTest.class.getResourceAsStream("jsqlparser_patch_1.diff"));
|
||||
|
||||
System.out.println(diff);
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(3);
|
||||
|
||||
assertThat(diff.getTail()).isEqualTo("2.17.1.windows.2\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseDiffBlock() {
|
||||
String[] files = UnifiedDiffReader.parseFileNames("diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java");
|
||||
assertThat(files).containsExactly("src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java", "src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkHeaderParsing() {
|
||||
Pattern pattern = UnifiedDiffReader.UNIFIED_DIFF_CHUNK_REGEXP;
|
||||
Matcher matcher = pattern.matcher("@@ -189,6 +189,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */");
|
||||
|
||||
assertTrue(matcher.find());
|
||||
assertEquals("189", matcher.group(1));
|
||||
assertEquals("189", matcher.group(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkHeaderParsing2() {
|
||||
//"^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@.*$"
|
||||
Pattern pattern = UnifiedDiffReader.UNIFIED_DIFF_CHUNK_REGEXP;
|
||||
Matcher matcher = pattern.matcher("@@ -189,6 +189,7 @@");
|
||||
|
||||
assertTrue(matcher.find());
|
||||
assertEquals("189", matcher.group(1));
|
||||
assertEquals("189", matcher.group(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkHeaderParsing3() {
|
||||
//"^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@.*$"
|
||||
Pattern pattern = UnifiedDiffReader.UNIFIED_DIFF_CHUNK_REGEXP;
|
||||
Matcher matcher = pattern.matcher("@@ -1,27 +1,27 @@");
|
||||
|
||||
assertTrue(matcher.find());
|
||||
assertEquals("1", matcher.group(1));
|
||||
assertEquals("1", matcher.group(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleParse2() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(UnifiedDiffReaderTest.class.getResourceAsStream("jsqlparser_patch_1.diff"));
|
||||
|
||||
System.out.println(diff);
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(3);
|
||||
|
||||
AbstractDelta<String> first = file1.getPatch().getDeltas().get(0);
|
||||
|
||||
assertThat(first.getSource().size()).isGreaterThan(0);
|
||||
assertThat(first.getTarget().size()).isGreaterThan(0);
|
||||
|
||||
assertThat(diff.getTail()).isEqualTo("2.17.1.windows.2\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimplePattern() {
|
||||
Pattern pattern = Pattern.compile("^\\+\\+\\+\\s");
|
||||
|
||||
Matcher m = pattern.matcher("+++ revised.txt");
|
||||
assertTrue(m.find());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue46() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue46.diff"));
|
||||
|
||||
System.out.println(diff);
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo(".vhd");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getTail()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue33() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue33.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("Main.java");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getTail()).isNull();
|
||||
assertThat(diff.getHeader()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue51() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue51.diff"));
|
||||
|
||||
System.out.println(diff);
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("f1");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file2 = diff.getFiles().get(1);
|
||||
assertThat(file2.getFromFile()).isEqualTo("f2");
|
||||
assertThat(file2.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getTail()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue79() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue79.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("test/Issue.java");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(0);
|
||||
|
||||
assertThat(diff.getTail()).isNull();
|
||||
assertThat(diff.getHeader()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue84() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue84.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("config/ant-phase-verify.xml");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file2 = diff.getFiles().get(1);
|
||||
assertThat(file2.getFromFile()).isEqualTo("/dev/null");
|
||||
assertThat(file2.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getTail()).isEqualTo("2.7.4");
|
||||
assertThat(diff.getHeader()).startsWith("From b53e612a2ab5ff15d14860e252f84c0f343fe93a Mon Sep 17 00:00:00 2001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue85() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue85.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
assertEquals(1, diff.getFiles().size());
|
||||
|
||||
final UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertEquals("diff -r 83e41b73d115 -r a4438263b228 tests/test-check-pyflakes.t",
|
||||
file1.getDiffCommand());
|
||||
assertEquals("tests/test-check-pyflakes.t", file1.getFromFile());
|
||||
assertEquals("tests/test-check-pyflakes.t", file1.getToFile());
|
||||
assertEquals(1, file1.getPatch().getDeltas().size());
|
||||
|
||||
assertNull(diff.getTail());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeStampRegexp() {
|
||||
assertThat("2019-04-18 13:49:39.516149751 +0200").matches(UnifiedDiffReader.TIMESTAMP_REGEXP);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue98() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue98.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
assertEquals(1, diff.getFiles().size());
|
||||
|
||||
final UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertEquals("100644",
|
||||
file1.getDeletedFileMode());
|
||||
assertEquals("src/test/java/se/bjurr/violations/lib/model/ViolationTest.java", file1.getFromFile());
|
||||
assertThat(diff.getTail()).isEqualTo("2.25.1");
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,27 @@
|
||||
package com.github.difflib;
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.TestConstants;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class GenerateUnifiedDiffTest {
|
||||
public class UnifiedDiffRoundTripTest {
|
||||
|
||||
private static List<String> fileToLines(String filename) throws FileNotFoundException, IOException {
|
||||
public static List<String> fileToLines(String filename) throws FileNotFoundException, IOException {
|
||||
List<String> lines = new ArrayList<>();
|
||||
String line = "";
|
||||
try (BufferedReader in = new BufferedReader(new FileReader(filename))) {
|
||||
@@ -28,7 +33,7 @@ public class GenerateUnifiedDiffTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateUnified() throws DiffException, IOException {
|
||||
public void testGenerateUnified() throws IOException {
|
||||
List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "original.txt");
|
||||
List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "revised.txt");
|
||||
|
||||
@@ -36,7 +41,7 @@ public class GenerateUnifiedDiffTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateUnifiedWithOneDelta() throws DiffException, IOException {
|
||||
public void testGenerateUnifiedWithOneDelta() throws IOException {
|
||||
List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_original.txt");
|
||||
List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_revised.txt");
|
||||
|
||||
@@ -44,17 +49,29 @@ public class GenerateUnifiedDiffTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateUnifiedDiffWithoutAnyDeltas() throws DiffException {
|
||||
public void testGenerateUnifiedDiffWithoutAnyDeltas() throws IOException {
|
||||
List<String> test = Arrays.asList("abc");
|
||||
Patch<String> patch = DiffUtils.diff(test, test);
|
||||
UnifiedDiffUtils.generateUnifiedDiff("abc", "abc", test, patch, 0);
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
UnifiedDiffWriter.write(
|
||||
UnifiedDiff.from("header", "tail", UnifiedDiffFile.from("abc", "abc", patch)),
|
||||
name -> test,
|
||||
writer, 0);
|
||||
|
||||
System.out.println(writer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff_Issue10() throws IOException {
|
||||
final List<String> baseLines = fileToLines(TestConstants.MOCK_FOLDER + "issue10_base.txt");
|
||||
final List<String> patchLines = fileToLines(TestConstants.MOCK_FOLDER + "issue10_patch.txt");
|
||||
final Patch<String> p = UnifiedDiffUtils.parseUnifiedDiff(patchLines);
|
||||
|
||||
UnifiedDiff unifiedDiff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
new ByteArrayInputStream(patchLines.stream().collect(joining("\n")).getBytes())
|
||||
);
|
||||
|
||||
final Patch<String> p = unifiedDiff.getFiles().get(0).getPatch();
|
||||
try {
|
||||
DiffUtils.patch(baseLines, p);
|
||||
} catch (PatchFailedException e) {
|
||||
@@ -66,14 +83,15 @@ public class GenerateUnifiedDiffTest {
|
||||
* Issue 12
|
||||
*/
|
||||
@Test
|
||||
public void testPatchWithNoDeltas() throws DiffException, IOException {
|
||||
@Disabled
|
||||
public void testPatchWithNoDeltas() throws IOException {
|
||||
final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_1.txt");
|
||||
final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_2.txt");
|
||||
verify(lines1, lines2, "issue11_1.txt", "issue11_2.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiff5() throws DiffException, IOException {
|
||||
public void testDiff5() throws IOException {
|
||||
final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "5A.txt");
|
||||
final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "5B.txt");
|
||||
verify(lines1, lines2, "5A.txt", "5B.txt");
|
||||
@@ -83,7 +101,7 @@ public class GenerateUnifiedDiffTest {
|
||||
* Issue 19
|
||||
*/
|
||||
@Test
|
||||
public void testDiffWithHeaderLineInText() throws DiffException {
|
||||
public void testDiffWithHeaderLineInText() throws IOException {
|
||||
List<String> original = new ArrayList<>();
|
||||
List<String> revised = new ArrayList<>();
|
||||
|
||||
@@ -99,22 +117,41 @@ public class GenerateUnifiedDiffTest {
|
||||
revised.add("test line 5");
|
||||
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
List<String> udiff = UnifiedDiffUtils.generateUnifiedDiff("original", "revised",
|
||||
original, patch, 10);
|
||||
UnifiedDiffUtils.parseUnifiedDiff(udiff);
|
||||
StringWriter writer = new StringWriter();
|
||||
UnifiedDiffWriter.write(
|
||||
UnifiedDiff.from("header", "tail", UnifiedDiffFile.from("original", "revised", patch)),
|
||||
name -> original,
|
||||
writer, 10);
|
||||
|
||||
System.out.println(writer.toString());
|
||||
|
||||
UnifiedDiff unifiedDiff = UnifiedDiffReader.parseUnifiedDiff(new ByteArrayInputStream(writer.toString().getBytes()));
|
||||
}
|
||||
|
||||
private void verify(List<String> origLines, List<String> revLines,
|
||||
String originalFile, String revisedFile) throws DiffException {
|
||||
String originalFile, String revisedFile) throws IOException {
|
||||
Patch<String> patch = DiffUtils.diff(origLines, revLines);
|
||||
List<String> unifiedDiff = UnifiedDiffUtils.generateUnifiedDiff(originalFile, revisedFile,
|
||||
origLines, patch, 10);
|
||||
|
||||
Patch<String> fromUnifiedPatch = UnifiedDiffUtils.parseUnifiedDiff(unifiedDiff);
|
||||
StringWriter writer = new StringWriter();
|
||||
UnifiedDiffWriter.write(
|
||||
UnifiedDiff.from("header", "tail", UnifiedDiffFile.from(originalFile, revisedFile, patch)),
|
||||
name -> origLines,
|
||||
writer, 10);
|
||||
|
||||
System.out.println(writer.toString());
|
||||
|
||||
UnifiedDiff unifiedDiff = UnifiedDiffReader.parseUnifiedDiff(new ByteArrayInputStream(writer.toString().getBytes()));
|
||||
|
||||
List<String> patchedLines;
|
||||
try {
|
||||
patchedLines = (List<String>) fromUnifiedPatch.applyTo(origLines);
|
||||
assertTrue(revLines.size() == patchedLines.size());
|
||||
// if (unifiedDiff.getFiles().isEmpty()) {
|
||||
// patchedLines = new ArrayList<>(origLines);
|
||||
// } else {
|
||||
// Patch<String> fromUnifiedPatch = unifiedDiff.getFiles().get(0).getPatch();
|
||||
// patchedLines = fromUnifiedPatch.applyTo(origLines);
|
||||
// }
|
||||
patchedLines = unifiedDiff.spplyPatchTo(file -> originalFile.equals(file), origLines);
|
||||
assertEquals(revLines.size(), patchedLines.size());
|
||||
for (int i = 0; i < revLines.size(); i++) {
|
||||
String l1 = revLines.get(i);
|
||||
String l2 = patchedLines.get(i);
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public class UnifiedDiffWriterTest {
|
||||
|
||||
public UnifiedDiffWriterTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrite() throws URISyntaxException, IOException {
|
||||
String str = readFile(UnifiedDiffReaderTest.class.getResource("jsqlparser_patch_1.diff").toURI(), Charset.defaultCharset());
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(new ByteArrayInputStream(str.getBytes()));
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
UnifiedDiffWriter.write(diff, f -> Collections.EMPTY_LIST, writer, 5);
|
||||
System.out.println(writer.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue 47
|
||||
*/
|
||||
@Test
|
||||
public void testWriteWithNewFile() throws URISyntaxException, IOException {
|
||||
|
||||
List<String> original = new ArrayList<>();
|
||||
List<String> revised = new ArrayList<>();
|
||||
|
||||
revised.add("line1");
|
||||
revised.add("line2");
|
||||
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
UnifiedDiff diff = new UnifiedDiff();
|
||||
diff.addFile( UnifiedDiffFile.from(null, "revised", patch) );
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
UnifiedDiffWriter.write(diff, f -> original, writer, 5);
|
||||
System.out.println(writer.toString());
|
||||
|
||||
String[] lines = writer.toString().split("\\n");
|
||||
|
||||
assertEquals("--- /dev/null", lines[0]);
|
||||
assertEquals("+++ revised", lines[1]);
|
||||
assertEquals("@@ -0,0 +1,2 @@", lines[2]);
|
||||
}
|
||||
|
||||
static String readFile(URI path, Charset encoding)
|
||||
throws IOException {
|
||||
byte[] encoded = Files.readAllBytes(Paths.get(path));
|
||||
return new String(encoded, encoding);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
MessageTime,MessageType,Instrument,InstrumentState,TradePrice,TradeVolume,TradeCond,TradeId,AskPrice1,AskVol1,BidPrice1,BidVol1,AskPrice2,AskVol2,BidPrice2,BidVol2,AskPrice3,AskVol3,BidPrice3,BidVol3,AskPrice4,AskVol4,BidPrice4,BidVol4,AskPrice5,AskVol5,BidPrice5,BidVol5
|
||||
2020-04-04T08:00:00.000Z,S,HHD_MAY20,Open,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T08:00:00.000Z,S,FHK_C23.5_MAY20,Open,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T13:49:11.522Z,Q,HHD_MAY20,,,,,,2.6,10,2.6,10,,,,,,,,,,,,,,,,
|
||||
2020-04-04T13:49:18.210Z,T,HHD_MAY20,,2.6,1,Screen,0,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T17:00:00.000Z,S,HHD_MAY20,Close,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T17:00:00.000Z,S,FHK_C23.5_MAY20,Close,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
@@ -0,0 +1,8 @@
|
||||
MessageTime,MessageType,Instrument,InstrumentState,TradePrice,TradeVolume,TradeCond,TradeId,AskPrice1,AskVol1,BidPrice1,BidVol1,AskPrice2,AskVol2,BidPrice2,BidVol2,AskPrice3,AskVol3,BidPrice3,BidVol3,AskPrice4,AskVol4,BidPrice4,BidVol4,AskPrice5,AskVol5,BidPrice5,BidVol5
|
||||
2020-04-02T08:00:00.000Z,S,HHD_MAY20,Open,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-02T08:00:00.000Z,S,FHK_C23.5_MAY20,Open,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T13:49:11.522Z,Q,HHD_MAY20,,,,,,2.6,10,2.6,10,,,,,,,,,,,,,,,,
|
||||
2020-04xs-04T17dw:00:00.000Z,Sdwdw,HHD_MAY20dwdw,Closdwde,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T13:49:18.210Z,T,HHD_MAY20,,2.6,2,Screen,0,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T17:00:00.000Z,S,HHD_MAY20,Close,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
2020-04-04T17:00:00.000Z,S,FHK_C23.5_MAY20,Close,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
@@ -0,0 +1,61 @@
|
||||
From 3209a16c55c1976d5b772c607fd4b9d5fb9f9483 Mon Sep 17 00:00:00 2001
|
||||
From: wumpz <t.warneke@gmx.net>
|
||||
Date: Tue, 19 Feb 2019 01:35:14 +0100
|
||||
Subject: [PATCH] fixes #753
|
||||
|
||||
---
|
||||
src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt | 5 +++--
|
||||
.../net/sf/jsqlparser/statement/select/SelectTest.java | 7 +++++++
|
||||
2 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
|
||||
index cd9bcd1..5f4b2b7 100644
|
||||
--- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
|
||||
+++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
|
||||
@@ -189,6 +189,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
|
||||
| <K_JOIN:"JOIN">
|
||||
| <K_KEEP:"KEEP">
|
||||
| <K_KEY:"KEY">
|
||||
+| <K_FN:"FN">
|
||||
| <K_LAST: "LAST">
|
||||
| <K_LATERAL:"LATERAL">
|
||||
| <K_LEADING:"LEADING">
|
||||
@@ -1039,7 +1040,7 @@ String RelObjectNameWithoutValue() :
|
||||
| tk=<K_INSERT> | tk=<K_INDEX> | tk=<K_PRIMARY> | tk=<K_ENABLE>
|
||||
| tk=<K_UNSIGNED>
|
||||
| tk=<K_TEMP> | tk=<K_TEMPORARY> | tk=<K_TYPE> | tk=<K_ISNULL>
|
||||
- | tk=<K_ZONE> | tk=<K_COLUMNS> | tk=<K_DESCRIBE>
|
||||
+ | tk=<K_ZONE> | tk=<K_COLUMNS> | tk=<K_DESCRIBE> | tk=<K_FN>
|
||||
/* | tk=<K_PLACING> | tk=<K_BOTH> | tk=<K_LEADING> | tk=<K_TRAILING> */
|
||||
)
|
||||
|
||||
@@ -3118,7 +3119,7 @@ Function Function() #Function:
|
||||
Expression expr1 = null;
|
||||
}
|
||||
{
|
||||
- ["{fn" { retval.setEscaped(true); } ]
|
||||
+ ["{" <K_FN> { retval.setEscaped(true); } ]
|
||||
|
||||
funcName=RelObjectNameExt()
|
||||
|
||||
diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
|
||||
index 7ee9b38..d39bfd3 100644
|
||||
--- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
|
||||
+++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java
|
||||
@@ -1063,6 +1063,13 @@ public class SelectTest {
|
||||
assertSqlCanBeParsedAndDeparsed("SELECT {fn concat(a, b)} AS COL");
|
||||
}
|
||||
|
||||
+ @Test
|
||||
+ public void testEscapedFunctionsIssue753() throws JSQLParserException {
|
||||
+ Statement stmt = CCJSqlParserUtil.parse("SELECT { fn test(0)} AS COL");
|
||||
+ assertEquals("SELECT {fn test(0)} AS COL", stmt.toString());
|
||||
+ assertSqlCanBeParsedAndDeparsed("SELECT fn FROM fn");
|
||||
+ }
|
||||
+
|
||||
@Test
|
||||
public void testNamedParametersPR702() throws JSQLParserException {
|
||||
assertSqlCanBeParsedAndDeparsed("SELECT substring(id, 2, 3), substring(id from 2 for 3), substring(id from 2), trim(BOTH ' ' from 'foo bar '), trim(LEADING ' ' from 'foo bar '), trim(TRAILING ' ' from 'foo bar '), trim(' ' from 'foo bar '), position('foo' in 'bar'), overlay('foo' placing 'bar' from 1), overlay('foo' placing 'bar' from 1 for 2) FROM my table");
|
||||
--
|
||||
2.17.1.windows.2
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
--- a/Main.java
|
||||
+++ b/Main.java
|
||||
@@ -2,2 +2,3 @@ public class Main {
|
||||
public static void main(String[] args) {
|
||||
+ System.out.println("Hello, world!");
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
--- a.vhd 2019-04-18 13:49:39.516149751 +0200
|
||||
+++ b.vhd 2019-04-18 11:33:08.372563078 +0200
|
||||
@@ -2819,3 +2819,2 @@
|
||||
--- some comment
|
||||
-bla
|
||||
-bla
|
||||
+
|
||||
+
|
||||
@@ -0,0 +1,12 @@
|
||||
diff -U0 old/f1 new/f1
|
||||
--- old/f1 2019-09-25 14:38:06.000000000 +0200
|
||||
+++ new/f1 2019-09-25 14:38:27.000000000 +0200
|
||||
@@ -1 +1 @@
|
||||
-a\nb
|
||||
+a\nb\nd
|
||||
diff -U0 old/f2 new/f2
|
||||
--- old/f2 2019-09-25 14:38:14.000000000 +0200
|
||||
+++ new/f2 2019-09-25 14:38:32.000000000 +0200
|
||||
@@ -1 +1 @@
|
||||
-a\nc
|
||||
+a\nb\nd
|
||||
@@ -0,0 +1,3 @@
|
||||
diff --git a/test/Issue.java b/test/Issue.java
|
||||
new file mode 100644
|
||||
index 00000000..9702606e
|
||||
@@ -0,0 +1,109 @@
|
||||
From b53e612a2ab5ff15d14860e252f84c0f343fe93a Mon Sep 17 00:00:00 2001
|
||||
From: nmancus1 <nmancus1
|
||||
Date: Thu, 4 Jun 2020 11:46:34 -0400
|
||||
Subject: [PATCH] minor: Add input file for Java14 instanceof with pattern
|
||||
matching (#7290)
|
||||
|
||||
---
|
||||
config/ant-phase-verify.xml | 2 +
|
||||
.../InputJava14InstanceofWithPatternMatching.java | 76 ++++++++++++++++++++++
|
||||
2 files changed, 78 insertions(+)
|
||||
create mode 100644 src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java14/InputJava14InstanceofWithPatternMatching.java
|
||||
|
||||
diff --git a/config/ant-phase-verify.xml b/config/ant-phase-verify.xml
|
||||
index d27ffef..e0285ce 100644
|
||||
--- a/config/ant-phase-verify.xml
|
||||
+++ b/config/ant-phase-verify.xml
|
||||
@@ -148,6 +148,8 @@
|
||||
<exclude name="**/InputMainFrameModelIncorrectClass.java"/>
|
||||
<exclude name="**/InputBeforeExecutionExclusionFileFilterIncorrectClass.java"/>
|
||||
<exclude name="**/InputJavaParser.java"/>
|
||||
+ <!-- until https://github.com/checkstyle/checkstyle/issues/7290 -->
|
||||
+ <exclude name="**/InputJava14InstanceofWithPatternMatching.java"/>
|
||||
<!-- Cannot parse until Java 14 support -->
|
||||
<exclude name="**/InputJava14Records.java"/>
|
||||
</fileset>
|
||||
diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java14/InputJava14InstanceofWithPatternMatching.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java14/InputJava14InstanceofWithPatternMatching.java
|
||||
new file mode 100644
|
||||
index 0000000..8fa3eba
|
||||
--- /dev/null
|
||||
+++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java14/InputJava14InstanceofWithPatternMatching.java
|
||||
@@ -0,0 +1,76 @@
|
||||
+//non-compiled with javac: Compilable with Java14
|
||||
+package com.puppycrawl.tools.checkstyle.grammar.java14;
|
||||
+
|
||||
+import java.util.Arrays;
|
||||
+import java.util.Locale;
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ ...... I removed it
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.7.4
|
||||
@@ -0,0 +1,31 @@
|
||||
# HG changeset patch
|
||||
# User Anton Shestakov <av6@dwimlabs.net>
|
||||
# Date 1591442367 -28800
|
||||
# Node ID a4438263b228dd3e2983d59095c6180b1411f0e8
|
||||
# Parent 83e41b73d115e3717943c2e5a83d36d05670384c
|
||||
tests: skip pyflakes for mercurial/thirdparty/
|
||||
|
||||
The current version of pyflakes (2.2.0) correctly detects one issue:
|
||||
|
||||
mercurial/thirdparty/selectors2.py:335:40 '...'.format(...) has unused arguments at position(s): 1
|
||||
|
||||
But we're not interested in fixing lint errors in third-party code, so we need
|
||||
to exclude at least selectors2.py. And in the discussion for this patch it was
|
||||
decided to just skip the entire thirdparty directory.
|
||||
|
||||
Differential Revision: https://phab.mercurial-scm.org/D8619
|
||||
|
||||
diff -r 83e41b73d115 -r a4438263b228 tests/test-check-pyflakes.t
|
||||
--- a/tests/test-check-pyflakes.t Tue Jun 09 17:13:26 2020 -0400
|
||||
+++ b/tests/test-check-pyflakes.t Sat Jun 06 19:19:27 2020 +0800
|
||||
@@ -16,9 +16,7 @@
|
||||
$ testrepohg locate 'set:**.py or grep("^#!.*python")' \
|
||||
> -X hgext/fsmonitor/pywatchman \
|
||||
> -X mercurial/pycompat.py -X contrib/python-zstandard \
|
||||
- > -X mercurial/thirdparty/cbor \
|
||||
- > -X mercurial/thirdparty/concurrent \
|
||||
- > -X mercurial/thirdparty/zope \
|
||||
+ > -X mercurial/thirdparty \
|
||||
> 2>/dev/null \
|
||||
> | xargs $PYTHON -m pyflakes 2>/dev/null | "$TESTDIR/filterpyflakes.py"
|
||||
contrib/perf.py:*:* undefined name 'xrange' (glob) (?)
|
||||
@@ -0,0 +1,55 @@
|
||||
From fd940c6f66126734e82c00889e7c987e11deea91 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Bjerre <tomas.bjerre85@gmail.com>
|
||||
Date: Sun, 6 Sep 2020 11:20:34 +0200
|
||||
Subject: [PATCH] removing file
|
||||
|
||||
---
|
||||
.../violations/lib/model/ViolationTest.java | 37 -------------------
|
||||
1 file changed, 37 deletions(-)
|
||||
delete mode 100644 src/test/java/se/bjurr/violations/lib/model/ViolationTest.java
|
||||
|
||||
diff --git a/src/test/java/se/bjurr/violations/lib/model/ViolationTest.java b/src/test/java/se/bjurr/violations/lib/model/ViolationTest.java
|
||||
deleted file mode 100644
|
||||
index 3e40b52..0000000
|
||||
--- a/src/test/java/se/bjurr/violations/lib/model/ViolationTest.java
|
||||
+++ /dev/null
|
||||
@@ -1,37 +0,0 @@
|
||||
-package se.bjurr.violations.lib.model;
|
||||
-
|
||||
-import static org.assertj.core.api.Assertions.assertThat;
|
||||
-import static se.bjurr.violations.lib.model.SEVERITY.ERROR;
|
||||
-import static se.bjurr.violations.lib.model.Violation.violationBuilder;
|
||||
-import static se.bjurr.violations.lib.reports.Parser.CHECKSTYLE;
|
||||
-
|
||||
-import org.junit.Test;
|
||||
-import se.bjurr.violations.lib.model.Violation.ViolationBuilder;
|
||||
-import uk.co.jemos.podam.api.PodamFactoryImpl;
|
||||
-
|
||||
-public class ViolationTest {
|
||||
-
|
||||
- @Test
|
||||
- public void testThatFilePathsAreAlwaysFronSlashes() {
|
||||
- final Violation violation =
|
||||
- violationBuilder() //
|
||||
- .setParser(CHECKSTYLE) //
|
||||
- .setFile("c:\\path\\to\\file.xml") //
|
||||
- .setMessage("message") //
|
||||
- .setSeverity(ERROR) //
|
||||
- .setStartLine(1) //
|
||||
- .build();
|
||||
- assertThat(violation.getFile()) //
|
||||
- .isEqualTo("c:/path/to/file.xml");
|
||||
- }
|
||||
-
|
||||
- @Test
|
||||
- public void testThatCopyConstructorWorks() {
|
||||
- final ViolationBuilder originalBuilder =
|
||||
- new PodamFactoryImpl().manufacturePojo(ViolationBuilder.class);
|
||||
- final Violation original = originalBuilder.build();
|
||||
- final Violation copied = new Violation(original);
|
||||
- assertThat(copied) //
|
||||
- .isEqualTo(original);
|
||||
- }
|
||||
-}
|
||||
--
|
||||
2.25.1
|
||||
8
java-diff-utils/src/test/resources/logging.properties
Normal file
8
java-diff-utils/src/test/resources/logging.properties
Normal file
@@ -0,0 +1,8 @@
|
||||
handlers=java.util.logging.ConsoleHandler
|
||||
|
||||
.level=INFO
|
||||
com.github.difflib.unifieddiff.level=FINE
|
||||
|
||||
java.util.logging.ConsoleHandler.level=INFO
|
||||
#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
|
||||
@@ -1,372 +1,372 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 Johannes E. Schindelin
|
||||
#
|
||||
|
||||
test_description='Test special whitespace in diff engine.
|
||||
|
||||
'
|
||||
. ./test-lib.sh
|
||||
. ../diff-lib.sh
|
||||
|
||||
# Ray Lehtiniemi's example
|
||||
|
||||
cat << EOF > x
|
||||
do {
|
||||
nothing;
|
||||
} while (0);
|
||||
EOF
|
||||
|
||||
git update-index --add x
|
||||
|
||||
cat << EOF > x
|
||||
do
|
||||
{
|
||||
nothing;
|
||||
}
|
||||
while (0);
|
||||
EOF
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index adf3937..6edc172 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,3 +1,5 @@
|
||||
-do {
|
||||
+do
|
||||
+{
|
||||
nothing;
|
||||
-} while (0);
|
||||
+}
|
||||
+while (0);
|
||||
EOF
|
||||
|
||||
git diff > out
|
||||
test_expect_success "Ray's example without options" 'test_cmp expect out'
|
||||
|
||||
git diff -w > out
|
||||
test_expect_success "Ray's example with -w" 'test_cmp expect out'
|
||||
|
||||
git diff -b > out
|
||||
test_expect_success "Ray's example with -b" 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
whitespace in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
EOF
|
||||
|
||||
git update-index x
|
||||
|
||||
tr '_' ' ' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
white space in the middle
|
||||
whitespace at end__
|
||||
unchanged line
|
||||
CR at end
|
||||
EOF
|
||||
|
||||
tr 'Q_' '\015 ' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
-whitespace change
|
||||
-whitespace in the middle
|
||||
-whitespace at end
|
||||
+ whitespace at beginning
|
||||
+whitespace change
|
||||
+white space in the middle
|
||||
+whitespace at end__
|
||||
unchanged line
|
||||
-CR at endQ
|
||||
+CR at end
|
||||
EOF
|
||||
git diff > out
|
||||
test_expect_success 'another test, without options' 'test_cmp expect out'
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
EOF
|
||||
git diff -w > out
|
||||
test_expect_success 'another test, with -w' 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
+ whitespace at beginning
|
||||
whitespace change
|
||||
-whitespace in the middle
|
||||
+white space in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
EOF
|
||||
git diff -b > out
|
||||
test_expect_success 'another test, with -b' 'test_cmp expect out'
|
||||
|
||||
test_expect_success 'check mixed spaces and tabs in indent' '
|
||||
|
||||
# This is indented with SP HT SP.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check mixed tabs and spaces in indent' '
|
||||
|
||||
# This is indented with HT SP HT.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors' '
|
||||
|
||||
git commit -m "snapshot" &&
|
||||
echo "foo();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --exit-code are not exclusive' '
|
||||
|
||||
git checkout x &&
|
||||
git diff --check --exit-code
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --quiet are not exclusive' '
|
||||
|
||||
git diff --check --quiet
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-tree)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git commit -m "new commit" x &&
|
||||
git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-tree)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git commit -m "another commit" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-tree)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git commit -m "yet another" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: off)' '
|
||||
|
||||
git config core.whitespace "-trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: on)' '
|
||||
|
||||
git config core.whitespace "trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: off)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "-space-before-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: on)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "space-before-tab" &&
|
||||
echo " foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
|
||||
|
||||
git config core.whitespace "-indent-with-non-tab"
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'line numbers in --check output are correct' '
|
||||
|
||||
echo "" > x &&
|
||||
echo "foo(); " >> x &&
|
||||
git diff --check | grep "x:2:"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff detects trailing blank lines' '
|
||||
echo "foo();" >x &&
|
||||
echo "" >>x &&
|
||||
git diff --check | grep "ends with blank"
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff allows new blank lines' '
|
||||
git checkout x &&
|
||||
mv x y &&
|
||||
(
|
||||
echo "/* This is new */" &&
|
||||
echo "" &&
|
||||
cat y
|
||||
) >x &&
|
||||
git diff --check
|
||||
'
|
||||
|
||||
test_expect_success 'combined diff with autocrlf conversion' '
|
||||
|
||||
git reset --hard &&
|
||||
echo >x hello &&
|
||||
git commit -m "one side" x &&
|
||||
git checkout HEAD^ &&
|
||||
echo >x goodbye &&
|
||||
git commit -m "the other side" x &&
|
||||
git config core.autocrlf true &&
|
||||
test_must_fail git merge master &&
|
||||
|
||||
git diff | sed -e "1,/^@@@/d" >actual &&
|
||||
! grep "^-" actual
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 Johannes E. Schindelin
|
||||
#
|
||||
|
||||
test_description='Test special whitespace in diff engine.
|
||||
|
||||
'
|
||||
. ./test-lib.sh
|
||||
. ../diff-lib.sh
|
||||
|
||||
# Ray Lehtiniemi's example
|
||||
|
||||
cat << EOF > x
|
||||
do {
|
||||
nothing;
|
||||
} while (0);
|
||||
EOF
|
||||
|
||||
git update-index --add x
|
||||
|
||||
cat << EOF > x
|
||||
do
|
||||
{
|
||||
nothing;
|
||||
}
|
||||
while (0);
|
||||
EOF
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index adf3937..6edc172 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,3 +1,5 @@
|
||||
-do {
|
||||
+do
|
||||
+{
|
||||
nothing;
|
||||
-} while (0);
|
||||
+}
|
||||
+while (0);
|
||||
EOF
|
||||
|
||||
git diff > out
|
||||
test_expect_success "Ray's example without options" 'test_cmp expect out'
|
||||
|
||||
git diff -w > out
|
||||
test_expect_success "Ray's example with -w" 'test_cmp expect out'
|
||||
|
||||
git diff -b > out
|
||||
test_expect_success "Ray's example with -b" 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
whitespace in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
EOF
|
||||
|
||||
git update-index x
|
||||
|
||||
tr '_' ' ' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
white space in the middle
|
||||
whitespace at end__
|
||||
unchanged line
|
||||
CR at end
|
||||
EOF
|
||||
|
||||
tr 'Q_' '\015 ' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
-whitespace change
|
||||
-whitespace in the middle
|
||||
-whitespace at end
|
||||
+ whitespace at beginning
|
||||
+whitespace change
|
||||
+white space in the middle
|
||||
+whitespace at end__
|
||||
unchanged line
|
||||
-CR at endQ
|
||||
+CR at end
|
||||
EOF
|
||||
git diff > out
|
||||
test_expect_success 'another test, without options' 'test_cmp expect out'
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
EOF
|
||||
git diff -w > out
|
||||
test_expect_success 'another test, with -w' 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
+ whitespace at beginning
|
||||
whitespace change
|
||||
-whitespace in the middle
|
||||
+white space in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
EOF
|
||||
git diff -b > out
|
||||
test_expect_success 'another test, with -b' 'test_cmp expect out'
|
||||
|
||||
test_expect_success 'check mixed spaces and tabs in indent' '
|
||||
|
||||
# This is indented with SP HT SP.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check mixed tabs and spaces in indent' '
|
||||
|
||||
# This is indented with HT SP HT.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors' '
|
||||
|
||||
git commit -m "snapshot" &&
|
||||
echo "foo();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --exit-code are not exclusive' '
|
||||
|
||||
git checkout x &&
|
||||
git diff --check --exit-code
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --quiet are not exclusive' '
|
||||
|
||||
git diff --check --quiet
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-tree)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git commit -m "new commit" x &&
|
||||
git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-tree)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git commit -m "another commit" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-tree)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git commit -m "yet another" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: off)' '
|
||||
|
||||
git config core.whitespace "-trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: on)' '
|
||||
|
||||
git config core.whitespace "trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: off)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "-space-before-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: on)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "space-before-tab" &&
|
||||
echo " foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
|
||||
|
||||
git config core.whitespace "-indent-with-non-tab"
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'line numbers in --check output are correct' '
|
||||
|
||||
echo "" > x &&
|
||||
echo "foo(); " >> x &&
|
||||
git diff --check | grep "x:2:"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff detects trailing blank lines' '
|
||||
echo "foo();" >x &&
|
||||
echo "" >>x &&
|
||||
git diff --check | grep "ends with blank"
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff allows new blank lines' '
|
||||
git checkout x &&
|
||||
mv x y &&
|
||||
(
|
||||
echo "/* This is new */" &&
|
||||
echo "" &&
|
||||
cat y
|
||||
) >x &&
|
||||
git diff --check
|
||||
'
|
||||
|
||||
test_expect_success 'combined diff with autocrlf conversion' '
|
||||
|
||||
git reset --hard &&
|
||||
echo >x hello &&
|
||||
git commit -m "one side" x &&
|
||||
git checkout HEAD^ &&
|
||||
echo >x goodbye &&
|
||||
git commit -m "the other side" x &&
|
||||
git config core.autocrlf true &&
|
||||
test_must_fail git merge master &&
|
||||
|
||||
git diff | sed -e "1,/^@@@/d" >actual &&
|
||||
! grep "^-" actual
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -1,381 +1,381 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 Johannes E. Schindelin
|
||||
#
|
||||
|
||||
test_description='Test special whitespace in diff engine.
|
||||
|
||||
'
|
||||
. ./test-lib.sh
|
||||
. ../diff-lib.sh
|
||||
|
||||
# Ray Lehtiniemi's example
|
||||
|
||||
cat << EOF > x
|
||||
do {
|
||||
nothing;
|
||||
} while (0);
|
||||
EOF
|
||||
|
||||
git update-index --add x
|
||||
|
||||
cat << EOF > x
|
||||
do
|
||||
{
|
||||
nothing;
|
||||
}
|
||||
while (0);
|
||||
EOF
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index adf3937..6edc172 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,3 +1,5 @@
|
||||
-do {
|
||||
+do
|
||||
+{
|
||||
nothing;
|
||||
-} while (0);
|
||||
+}
|
||||
+while (0);
|
||||
EOF
|
||||
|
||||
git diff > out
|
||||
test_expect_success "Ray's example without options" 'test_cmp expect out'
|
||||
|
||||
git diff -w > out
|
||||
test_expect_success "Ray's example with -w" 'test_cmp expect out'
|
||||
|
||||
git diff -b > out
|
||||
test_expect_success "Ray's example with -b" 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
whitespace in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
EOF
|
||||
|
||||
git update-index x
|
||||
|
||||
tr '_' ' ' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
white space in the middle
|
||||
whitespace at end__
|
||||
unchanged line
|
||||
CR at end
|
||||
EOF
|
||||
|
||||
tr 'Q_' '\015 ' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
-whitespace change
|
||||
-whitespace in the middle
|
||||
-whitespace at end
|
||||
+ whitespace at beginning
|
||||
+whitespace change
|
||||
+white space in the middle
|
||||
+whitespace at end__
|
||||
unchanged line
|
||||
-CR at endQ
|
||||
+CR at end
|
||||
EOF
|
||||
git diff > out
|
||||
test_expect_success 'another test, without options' 'test_cmp expect out'
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
EOF
|
||||
git diff -w > out
|
||||
test_expect_success 'another test, with -w' 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
+ whitespace at beginning
|
||||
whitespace change
|
||||
-whitespace in the middle
|
||||
+white space in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
git diff -b --ignore-space-at-eol > out
|
||||
test_expect_failure 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
EOF
|
||||
git diff -b > out
|
||||
test_expect_success 'another test, with -b' 'test_cmp expect out'
|
||||
|
||||
test_expect_success 'check mixed spaces and tabs in indent' '
|
||||
|
||||
# This is indented with SP HT SP.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check mixed tabs and spaces in indent' '
|
||||
|
||||
# This is indented with HT SP HT.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors' '
|
||||
|
||||
git commit -m "snapshot" &&
|
||||
echo "foo();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --exit-code are not exclusive' '
|
||||
|
||||
git checkout x &&
|
||||
git diff --check --exit-code
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --quiet are not exclusive' '
|
||||
|
||||
git diff --check --quiet
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-tree)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git commit -m "new commit" x &&
|
||||
git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-tree)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git commit -m "another commit" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-tree)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git commit -m "yet another" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: off)' '
|
||||
|
||||
git config core.whitespace "-trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: on)' '
|
||||
|
||||
git config core.whitespace "trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: off)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "-space-before-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: on)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "space-before-tab" &&
|
||||
echo " foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
|
||||
|
||||
git config core.whitespace "-indent-with-non-tab"
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'line numbers in --check output are correct' '
|
||||
|
||||
echo "" > x &&
|
||||
echo "foo(); " >> x &&
|
||||
git diff --check | grep "x:2:"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff detects trailing blank lines' '
|
||||
echo "foo();" >x &&
|
||||
echo "" >>x &&
|
||||
git diff --check | grep "ends with blank"
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff allows new blank lines' '
|
||||
git checkout x &&
|
||||
mv x y &&
|
||||
(
|
||||
echo "/* This is new */" &&
|
||||
echo "" &&
|
||||
cat y
|
||||
) >x &&
|
||||
git diff --check
|
||||
'
|
||||
|
||||
test_expect_success 'combined diff with autocrlf conversion' '
|
||||
|
||||
git reset --hard &&
|
||||
echo >x hello &&
|
||||
git commit -m "one side" x &&
|
||||
git checkout HEAD^ &&
|
||||
echo >x goodbye &&
|
||||
git commit -m "the other side" x &&
|
||||
git config core.autocrlf true &&
|
||||
test_must_fail git merge master &&
|
||||
|
||||
git diff | sed -e "1,/^@@@/d" >actual &&
|
||||
! grep "^-" actual
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 Johannes E. Schindelin
|
||||
#
|
||||
|
||||
test_description='Test special whitespace in diff engine.
|
||||
|
||||
'
|
||||
. ./test-lib.sh
|
||||
. ../diff-lib.sh
|
||||
|
||||
# Ray Lehtiniemi's example
|
||||
|
||||
cat << EOF > x
|
||||
do {
|
||||
nothing;
|
||||
} while (0);
|
||||
EOF
|
||||
|
||||
git update-index --add x
|
||||
|
||||
cat << EOF > x
|
||||
do
|
||||
{
|
||||
nothing;
|
||||
}
|
||||
while (0);
|
||||
EOF
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index adf3937..6edc172 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,3 +1,5 @@
|
||||
-do {
|
||||
+do
|
||||
+{
|
||||
nothing;
|
||||
-} while (0);
|
||||
+}
|
||||
+while (0);
|
||||
EOF
|
||||
|
||||
git diff > out
|
||||
test_expect_success "Ray's example without options" 'test_cmp expect out'
|
||||
|
||||
git diff -w > out
|
||||
test_expect_success "Ray's example with -w" 'test_cmp expect out'
|
||||
|
||||
git diff -b > out
|
||||
test_expect_success "Ray's example with -b" 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
whitespace in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
EOF
|
||||
|
||||
git update-index x
|
||||
|
||||
tr '_' ' ' << EOF > x
|
||||
whitespace at beginning
|
||||
whitespace change
|
||||
white space in the middle
|
||||
whitespace at end__
|
||||
unchanged line
|
||||
CR at end
|
||||
EOF
|
||||
|
||||
tr 'Q_' '\015 ' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
-whitespace change
|
||||
-whitespace in the middle
|
||||
-whitespace at end
|
||||
+ whitespace at beginning
|
||||
+whitespace change
|
||||
+white space in the middle
|
||||
+whitespace at end__
|
||||
unchanged line
|
||||
-CR at endQ
|
||||
+CR at end
|
||||
EOF
|
||||
git diff > out
|
||||
test_expect_success 'another test, without options' 'test_cmp expect out'
|
||||
|
||||
cat << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
EOF
|
||||
git diff -w > out
|
||||
test_expect_success 'another test, with -w' 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
@@ -1,6 +1,6 @@
|
||||
-whitespace at beginning
|
||||
+ whitespace at beginning
|
||||
whitespace change
|
||||
-whitespace in the middle
|
||||
+white space in the middle
|
||||
whitespace at end
|
||||
unchanged line
|
||||
CR at endQ
|
||||
git diff -b --ignore-space-at-eol > out
|
||||
test_expect_failure 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out'
|
||||
|
||||
tr 'Q' '\015' << EOF > expect
|
||||
diff --git a/x b/x
|
||||
index d99af23..8b32fb5 100644
|
||||
--- a/x
|
||||
+++ b/x
|
||||
EOF
|
||||
git diff -b > out
|
||||
test_expect_success 'another test, with -b' 'test_cmp expect out'
|
||||
|
||||
test_expect_success 'check mixed spaces and tabs in indent' '
|
||||
|
||||
# This is indented with SP HT SP.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check mixed tabs and spaces in indent' '
|
||||
|
||||
# This is indented with HT SP HT.
|
||||
echo " foo();" > x &&
|
||||
git diff --check | grep "space before tab in indent"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors' '
|
||||
|
||||
git commit -m "snapshot" &&
|
||||
echo "foo();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --exit-code are not exclusive' '
|
||||
|
||||
git checkout x &&
|
||||
git diff --check --exit-code
|
||||
|
||||
'
|
||||
|
||||
test_expect_success '--check and --quiet are not exclusive' '
|
||||
|
||||
git diff --check --quiet
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff --cached --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with no whitespace errors (diff-index)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git add x &&
|
||||
git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with trailing whitespace (diff-index)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check staged with space before tab in indent (diff-index)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git add x &&
|
||||
test_must_fail git diff-index --cached --check HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with no whitespace errors (diff-tree)' '
|
||||
|
||||
echo "foo();" > x &&
|
||||
git commit -m "new commit" x &&
|
||||
git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with trailing whitespace (diff-tree)' '
|
||||
|
||||
echo "foo(); " > x &&
|
||||
git commit -m "another commit" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check with space before tab in indent (diff-tree)' '
|
||||
|
||||
# indent has space followed by hard tab
|
||||
echo " foo();" > x &&
|
||||
git commit -m "yet another" x &&
|
||||
test_must_fail git diff-tree --check HEAD^ HEAD
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: off)' '
|
||||
|
||||
git config core.whitespace "-trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check trailing whitespace (trailing-space: on)' '
|
||||
|
||||
git config core.whitespace "trailing-space" &&
|
||||
echo "foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: off)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "-space-before-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check space before tab in indent (space-before-tab: on)' '
|
||||
|
||||
# indent contains space followed by HT
|
||||
git config core.whitespace "space-before-tab" &&
|
||||
echo " foo (); " > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
|
||||
|
||||
git config core.whitespace "-indent-with-non-tab"
|
||||
echo " foo ();" > x &&
|
||||
git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
|
||||
|
||||
git config core.whitespace "indent-with-non-tab" &&
|
||||
echo " foo ();" > x &&
|
||||
test_must_fail git diff --check
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'line numbers in --check output are correct' '
|
||||
|
||||
echo "" > x &&
|
||||
echo "foo(); " >> x &&
|
||||
git diff --check | grep "x:2:"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff detects trailing blank lines' '
|
||||
echo "foo();" >x &&
|
||||
echo "" >>x &&
|
||||
git diff --check | grep "ends with blank"
|
||||
'
|
||||
|
||||
test_expect_success 'checkdiff allows new blank lines' '
|
||||
git checkout x &&
|
||||
mv x y &&
|
||||
(
|
||||
echo "/* This is new */" &&
|
||||
echo "" &&
|
||||
cat y
|
||||
) >x &&
|
||||
git diff --check
|
||||
'
|
||||
|
||||
test_expect_success 'combined diff with autocrlf conversion' '
|
||||
|
||||
git reset --hard &&
|
||||
echo >x hello &&
|
||||
git commit -m "one side" x &&
|
||||
git checkout HEAD^ &&
|
||||
echo >x goodbye &&
|
||||
git commit -m "the other side" x &&
|
||||
git config core.autocrlf true &&
|
||||
test_must_fail git merge master &&
|
||||
|
||||
git diff | sed -e "1,/^@@@/d" >actual &&
|
||||
! grep "^-" actual
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
|
||||
9
java-diff-utils/src/test/resources/mocks/issue15_1.txt
Normal file
9
java-diff-utils/src/test/resources/mocks/issue15_1.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, NULLABLE,
|
||||
ACTIONS_C17005, ID, NUMBER, 22, 19, N,
|
||||
ACTIONS_C17005, ISSUEID, NUMBER, 22, 19, Y,
|
||||
ACTIONS_C17005, MODIFIED, NUMBER, 22, 10, Y,
|
||||
ACTIONS_C17005, TABLE, VARCHAR2, 1020, null, Y,
|
||||
ACTIONS_C17005, S_NAME, CLOB, 4000, null, Y,
|
||||
ACTIONS_C17008, ID, NUMBER, 22, 19, N,
|
||||
ACTIONS_C17008, ISSUEID, NUMBER, 22, 19, Y,
|
||||
ACTIONS_C17008, MODIFIED, NUMBER, 22, 10, Y,
|
||||
9
java-diff-utils/src/test/resources/mocks/issue15_2.txt
Normal file
9
java-diff-utils/src/test/resources/mocks/issue15_2.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, NULLABLE,
|
||||
ACTIONS_C16913, ID, NUMBER, 22, 19, N,
|
||||
ACTIONS_C16913, ISSUEID, NUMBER, 22, 19, Y,
|
||||
ACTIONS_C16913, MODIFIED, NUMBER, 22, 10, Y,
|
||||
ACTIONS_C16913, VRS, NUMBER, 22, 1, Y,
|
||||
ACTIONS_C16913, ZTABS, VARCHAR2, 255, null, Y,
|
||||
ACTIONS_C16913, ZTABS_S, VARCHAR2, 255, null, Y,
|
||||
ACTIONS_C16913, TASK, VARCHAR2, 255, null, Y,
|
||||
ACTIONS_C16913, HOURS_SPENT, VARCHAR2, 255, null, Y,
|
||||
29
java-diff-utils/src/test/resources/mocks/issue89_patch.txt
Normal file
29
java-diff-utils/src/test/resources/mocks/issue89_patch.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
--- Origin.java 2020-06-11 11:06:21.000000000 +0800
|
||||
+++ Update.java 2020-06-11 10:59:48.000000000 +0800
|
||||
@@ -1,9 +1,17 @@
|
||||
package checkstyle_demo.PatchSuppression.MultiChangeInOneFile;
|
||||
|
||||
-public class Origin {
|
||||
+public class Update {
|
||||
public void test1() {
|
||||
|
||||
}
|
||||
+
|
||||
+ public void test2() {
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ public void test3() {
|
||||
+
|
||||
+ }
|
||||
}
|
||||
|
||||
class BasicTest {
|
||||
@@ -16,5 +24,7 @@
|
||||
class Test2 {
|
||||
public void test1() {
|
||||
System.out.println();
|
||||
+ System.out.println();
|
||||
+ System.out.println();
|
||||
}
|
||||
}
|
||||
30
java-diff-utils/src/test/resources/mocks/issue89_revised.txt
Normal file
30
java-diff-utils/src/test/resources/mocks/issue89_revised.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
package checkstyle_demo.PatchSuppression.MultiChangeInOneFile;
|
||||
|
||||
public class issue89_revised {
|
||||
public void test1() {
|
||||
|
||||
}
|
||||
|
||||
public void test2() {
|
||||
|
||||
}
|
||||
|
||||
public void test3() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
private int i;
|
||||
void foo() {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public void test1() {
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-shared-configuration>
|
||||
<!--
|
||||
<!--
|
||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||
The configuration is intended to be shared among all the users of project and
|
||||
therefore it is assumed to be part of version control checkout.
|
||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||
-->
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||
-->
|
||||
<netbeans.compile.on.save>none</netbeans.compile.on.save>
|
||||
<com-junichi11-netbeans-changelf.enable>false</com-junichi11-netbeans-changelf.enable>
|
||||
<com-junichi11-netbeans-changelf.use-project>true</com-junichi11-netbeans-changelf.use-project>
|
||||
<com-junichi11-netbeans-changelf.lf-kind>LF</com-junichi11-netbeans-changelf.lf-kind>
|
||||
<com-junichi11-netbeans-changelf.use-global>false</com-junichi11-netbeans-changelf.use-global>
|
||||
</properties>
|
||||
<netbeans.compile.on.save>none</netbeans.compile.on.save>
|
||||
<com-junichi11-netbeans-changelf.enable>false</com-junichi11-netbeans-changelf.enable>
|
||||
<com-junichi11-netbeans-changelf.use-project>true</com-junichi11-netbeans-changelf.use-project>
|
||||
<com-junichi11-netbeans-changelf.lf-kind>LF</com-junichi11-netbeans-changelf.lf-kind>
|
||||
<com-junichi11-netbeans-changelf.use-global>false</com-junichi11-netbeans-changelf.use-global>
|
||||
<netbeans.hint.jdkPlatform>JDK_1.8</netbeans.hint.jdkPlatform>
|
||||
</properties>
|
||||
</project-shared-configuration>
|
||||
|
||||
471
pom.xml
471
pom.xml
@@ -1,249 +1,191 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.github.wumpz</groupId>
|
||||
<artifactId>diffutils</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.2</version>
|
||||
<name>java-diff-utils</name>
|
||||
<description>The DiffUtils library for computing diffs, applying patches, generationg side-by-side view in Java.</description>
|
||||
<url>https://github.com/wumpz/java-diff-utils</url>
|
||||
<inceptionYear>2009</inceptionYear>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.8</version>
|
||||
<name>java-diff-utils-parent</name>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>java-diff-utils</module>
|
||||
<module>java-diff-utils-jgit</module>
|
||||
</modules>
|
||||
<description>The DiffUtils library for computing diffs, applying patches, generationg side-by-side view in Java.</description>
|
||||
<url>https://github.com/java-diff-utils/java-diff-utils</url>
|
||||
<inceptionYear>2009</inceptionYear>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>sonatype-nexus-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>sonatype-nexus-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/wumpz/java-diff-utils.git</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com:wumpz/java-diff-utils.git</developerConnection>
|
||||
<url>https://github.com/wumpz/java-diff-utils.git</url>
|
||||
<tag>diffutils-2.2</tag>
|
||||
</scm>
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/java-diff-utils/java-diff-utils.git</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com:java-diff-utils/java-diff-utils.git</developerConnection>
|
||||
<url>https://github.com/java-diff-utils/java-diff-utils.git</url>
|
||||
<tag>java-diff-utils-parent-4.8</tag>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
<system>GitHub Issues</system>
|
||||
<url>https://github.com/java-diff-utils/java-diff-utils/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub Issues</system>
|
||||
<url>https://github.com/wumpz/java-diff-utils/issues</url>
|
||||
</issueManagement>
|
||||
<organization>
|
||||
<name>java-diff-utils</name>
|
||||
</organization>
|
||||
|
||||
<organization>
|
||||
<name>java-diff-utils</name>
|
||||
</organization>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Tobias Warneke</name>
|
||||
<email>t.warneke@gmx.net</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Tobias Warneke</name>
|
||||
<email>t.warneke@gmx.net</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Dmitry Naumenko</name>
|
||||
<email>dm.naumenko@gmail.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Juanco Anez</name>
|
||||
<email>juanco@suigeneris.org</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<type>jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>4.4.1.201607150455-r</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.googlecode.javaewah</groupId>
|
||||
<artifactId>JavaEWAH</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Make this JAR OSGi ready -->
|
||||
<!-- We want to keep packaging type as jar. Therefore we need to customize the MANIFEST.MF.
|
||||
See http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html
|
||||
-->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.4</version>
|
||||
<configuration>
|
||||
<additionalparam>${javadoc.opts}</additionalparam>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/LR*.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<localCheckout>true</localCheckout>
|
||||
<pushChanges>false</pushChanges>
|
||||
<mavenExecutorId>forked-path</mavenExecutorId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.17</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>verify-style</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<logViolationsToConsole>true</logViolationsToConsole>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
|
||||
<checkstyleRules>
|
||||
<module name="Checker">
|
||||
<module name="SuppressWarningsFilter" />
|
||||
<module name="FileTabCharacter" />
|
||||
<!-- git checkout may change linefeeds on the fly
|
||||
<module name="RegexpMultiline">
|
||||
<property name="format" value="(?s:(\r\n|\r).*)" />
|
||||
<property name="message" value="CRLF and CR line endings are prohibited, but this file uses them." />
|
||||
</module>
|
||||
-->
|
||||
<module name="TreeWalker">
|
||||
<module name="AvoidNestedBlocks" />
|
||||
<module name="ConstantName" />
|
||||
<module name="EmptyCatchBlock" />
|
||||
<module name="EmptyStatement" />
|
||||
<module name="MissingOverride" />
|
||||
<module name="MultipleVariableDeclarations" />
|
||||
<module name="ParameterAssignment" />
|
||||
<module name="StringLiteralEquality" />
|
||||
<module name="RedundantImport" />
|
||||
<module name="UnusedImports" />
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.6.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.15.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<localCheckout>true</localCheckout>
|
||||
<pushChanges>false</pushChanges>
|
||||
<mavenExecutorId>forked-path</mavenExecutorId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<configuration>
|
||||
<additionalparam>${javadoc.opts}</additionalparam>
|
||||
<doclint>none</doclint>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>verify-style</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<logViolationsToConsole>true</logViolationsToConsole>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
<sourceDirectories>${project.build.sourceDirectory}</sourceDirectories>
|
||||
<checkstyleRules>
|
||||
<module name="Checker">
|
||||
<module name="SuppressWarningsFilter" />
|
||||
<module name="FileTabCharacter" />
|
||||
<module name="TreeWalker">
|
||||
<module name="SuppressionCommentFilter" />
|
||||
<module name="AvoidNestedBlocks" />
|
||||
<module name="ConstantName" />
|
||||
<module name="EmptyCatchBlock" />
|
||||
<module name="EmptyStatement" />
|
||||
<module name="MissingOverride" />
|
||||
<module name="MultipleVariableDeclarations" />
|
||||
<module name="ParameterAssignment" />
|
||||
<module name="StringLiteralEquality" />
|
||||
<module name="RedundantImport" />
|
||||
<module name="UnusedImports" />
|
||||
|
||||
<module name="WhitespaceAfter" />
|
||||
<module name="WhitespaceAfter" />
|
||||
|
||||
<module name="NeedBraces" />
|
||||
<module name="UnnecessaryParentheses" />
|
||||
<module name="LeftCurly" />
|
||||
<module name="RightCurly" />
|
||||
<module name="NeedBraces" />
|
||||
<module name="UnnecessaryParentheses" />
|
||||
<module name="LeftCurly" />
|
||||
<module name="RightCurly" />
|
||||
|
||||
<module name="SuppressWarningsHolder" />
|
||||
</module>
|
||||
</module>
|
||||
</checkstyleRules>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>6.19</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<module name="SuppressWarningsHolder" />
|
||||
</module>
|
||||
</module>
|
||||
</checkstyleRules>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>8.29</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M4</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/LR*.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>sign-release-artifacts</id>
|
||||
<activation>
|
||||
@@ -274,31 +216,30 @@
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>doclint-java8-disable</id>
|
||||
<activation>
|
||||
<jdk>[1.8,)</jdk>
|
||||
</activation>
|
||||
<properties>
|
||||
<javadoc.opts>-Xdoclint:none</javadoc.opts>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>long-running-tests</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>xxx</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<profile>
|
||||
<id>doclint-java8-disable</id>
|
||||
<activation>
|
||||
<jdk>[1.8,)</jdk>
|
||||
</activation>
|
||||
<properties>
|
||||
<javadoc.opts>-Xdoclint:none</javadoc.opts>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>long-running-tests</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>xxx</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.algorithm;
|
||||
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The general interface for computing diffs between two lists of elements of type T.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public interface DiffAlgorithm<T> {
|
||||
|
||||
/**
|
||||
* Computes the difference between the original sequence and the revised sequence and returns it as a {@link Patch}
|
||||
* object.
|
||||
*
|
||||
* @param original The original sequence. Must not be {@code null}.
|
||||
* @param revised The revised sequence. Must not be {@code null}.
|
||||
* @return The patch representing the diff of the given sequences. Never {@code null}.
|
||||
*/
|
||||
public default List<Change> diff(T[] original, T[] revised) throws DiffException {
|
||||
return diff(Arrays.asList(original), Arrays.asList(revised));
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original sequence and the revised sequence and returns it as a {@link Patch}
|
||||
* object.
|
||||
*
|
||||
* @param original The original sequence. Must not be {@code null}.
|
||||
* @param revised The revised sequence. Must not be {@code null}.
|
||||
* @return The patch representing the diff of the given sequences. Never {@code null}.
|
||||
*/
|
||||
public List<Change> diff(List<T> original, List<T> revised) throws DiffException;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.algorithm;
|
||||
|
||||
public class DiffException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DiffException() {
|
||||
}
|
||||
|
||||
public DiffException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.algorithm;
|
||||
|
||||
/**
|
||||
* Thrown whenever the differencing engine cannot produce the differences between two revisions of ta text.
|
||||
*
|
||||
* @see MyersDiff
|
||||
* @see difflib.DiffAlgorithm
|
||||
*/
|
||||
public class DifferentiationFailedException extends DiffException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DifferentiationFailedException() {
|
||||
}
|
||||
|
||||
public DifferentiationFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes the change-delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class ChangeDelta<T> extends Delta<T> {
|
||||
|
||||
/**
|
||||
* Creates a change delta with the two given chunks.
|
||||
*
|
||||
* @param original The original chunk. Must not be {@code null}.
|
||||
* @param revised The original chunk. Must not be {@code null}.
|
||||
*/
|
||||
public ChangeDelta(Chunk<T> original, Chunk<T> revised) {
|
||||
super(DeltaType.CHANGE, original, revised);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verify(target);
|
||||
int position = getOriginal().getPosition();
|
||||
int size = getOriginal().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
int i = 0;
|
||||
for (T line : getRevised().getLines()) {
|
||||
target.add(position + i, line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
int position = getRevised().getPosition();
|
||||
int size = getRevised().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
int i = 0;
|
||||
for (T line : getOriginal().getLines()) {
|
||||
target.add(position + i, line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[ChangeDelta, position: " + getOriginal().getPosition() + ", lines: "
|
||||
+ getOriginal().getLines() + " to " + getRevised().getLines() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes the delete-delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class DeleteDelta<T> extends Delta<T> {
|
||||
|
||||
/**
|
||||
* Creates a change delta with the two given chunks.
|
||||
*
|
||||
* @param original The original chunk. Must not be {@code null}.
|
||||
* @param revised The original chunk. Must not be {@code null}.
|
||||
*/
|
||||
public DeleteDelta(Chunk<T> original, Chunk<T> revised) {
|
||||
super(DeltaType.DELETE, original, revised);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verify(target);
|
||||
int position = getOriginal().getPosition();
|
||||
int size = getOriginal().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
int position = this.getRevised().getPosition();
|
||||
List<T> lines = this.getOriginal().getLines();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
target.add(position + i, lines.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[DeleteDelta, position: " + getOriginal().getPosition() + ", lines: "
|
||||
+ getOriginal().getLines() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Describes the delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public abstract class Delta<T> {
|
||||
|
||||
private final DeltaType deltaType;
|
||||
private final Chunk<T> original;
|
||||
private final Chunk<T> revised;
|
||||
|
||||
/**
|
||||
* Construct the delta for original and revised chunks
|
||||
*
|
||||
* @param original Chunk describing the original text. Must not be {@code null}.
|
||||
* @param revised Chunk describing the revised text. Must not be {@code null}.
|
||||
*/
|
||||
public Delta(DeltaType deltaType, Chunk<T> original, Chunk<T> revised) {
|
||||
Objects.requireNonNull(deltaType, "deltaType must not be null");
|
||||
Objects.requireNonNull(original, "original must not be null");
|
||||
Objects.requireNonNull(revised, "revised must not be null");
|
||||
|
||||
this.deltaType = deltaType;
|
||||
this.original = original;
|
||||
this.revised = revised;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that this delta can be used to patch the given text.
|
||||
*
|
||||
* @param target the text to patch.
|
||||
* @throws PatchFailedException if the patch cannot be applied.
|
||||
*/
|
||||
public void verify(List<T> target) throws PatchFailedException {
|
||||
getOriginal().verify(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this delta as the patch for a given target
|
||||
*
|
||||
* @param target the given target
|
||||
* @throws PatchFailedException
|
||||
*/
|
||||
public abstract void applyTo(List<T> target) throws PatchFailedException;
|
||||
|
||||
/**
|
||||
* Cancel this delta for a given revised text. The action is opposite to patch.
|
||||
*
|
||||
* @param target the given revised text
|
||||
*/
|
||||
public abstract void restore(List<T> target);
|
||||
|
||||
public final DeltaType getType() {
|
||||
return deltaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Chunk describing the original text.
|
||||
*/
|
||||
public Chunk<T> getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Chunk describing the revised text.
|
||||
*/
|
||||
public Chunk<T> getRevised() {
|
||||
return revised;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((original == null) ? 0 : original.hashCode());
|
||||
result = prime * result + ((revised == null) ? 0 : revised.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Delta<T> other = (Delta) obj;
|
||||
if (original == null) {
|
||||
if (other.original != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!original.equals(other.original)) {
|
||||
return false;
|
||||
}
|
||||
if (revised == null) {
|
||||
if (other.revised != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!revised.equals(other.revised)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
/**
|
||||
* Base class for all exceptions emanating from this package.
|
||||
*
|
||||
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
|
||||
*/
|
||||
public class DiffException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DiffException() {
|
||||
}
|
||||
|
||||
public DiffException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes the add-delta between original and revised texts.
|
||||
*
|
||||
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
|
||||
* @param T The type of the compared elements in the 'lines'.
|
||||
*/
|
||||
public final class InsertDelta<T> extends Delta<T> {
|
||||
|
||||
/**
|
||||
* Creates an insert delta with the two given chunks.
|
||||
*
|
||||
* @param original The original chunk. Must not be {@code null}.
|
||||
* @param revised The original chunk. Must not be {@code null}.
|
||||
*/
|
||||
public InsertDelta(Chunk<T> original, Chunk<T> revised) {
|
||||
super(DeltaType.INSERT, original, revised);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(List<T> target) throws PatchFailedException {
|
||||
verify(target);
|
||||
int position = this.getOriginal().getPosition();
|
||||
List<T> lines = this.getRevised().getLines();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
target.add(position + i, lines.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restore(List<T> target) {
|
||||
int position = getRevised().getPosition();
|
||||
int size = getRevised().size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
target.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[InsertDelta, position: " + getOriginal().getPosition()
|
||||
+ ", lines: " + getRevised().getLines() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*-
|
||||
* #%L
|
||||
* java-diff-utils
|
||||
* %%
|
||||
* Copyright (C) 2009 - 2017 java-diff-utils
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package com.github.difflib.patch;
|
||||
|
||||
/**
|
||||
* Thrown whenever a delta cannot be applied as a patch to a given text.
|
||||
*
|
||||
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
|
||||
*/
|
||||
public class PatchFailedException extends DiffException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PatchFailedException() {
|
||||
}
|
||||
|
||||
public PatchFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.jgit;
|
||||
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author toben
|
||||
*/
|
||||
public class HistogramDiffTest {
|
||||
|
||||
public HistogramDiffTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of diff method, of class HistogramDiff.
|
||||
*/
|
||||
@Test
|
||||
public void testDiff() throws DiffException, PatchFailedException {
|
||||
List<String> orgList = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revList = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(orgList, revList, new HistogramDiff().diff(orgList, revList));
|
||||
System.out.println(patch);
|
||||
assertNotNull(patch);
|
||||
assertEquals(3, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [DeleteDelta, position: 3, lines: [A, B]], [InsertDelta, position: 7, lines: [B, A, C]]]}", patch.toString());
|
||||
|
||||
List<String> patched = patch.applyTo(orgList);
|
||||
assertEquals(revList, patched);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.jgit;
|
||||
|
||||
import static com.github.difflib.DiffUtilsTest.readStringListFromInputStream;
|
||||
import com.github.difflib.TestConstants;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipFile;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author toben
|
||||
*/
|
||||
public class LRHistogramDiffTest {
|
||||
|
||||
public LRHistogramDiffTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException, DiffException, PatchFailedException {
|
||||
ZipFile zip = new ZipFile(TestConstants.MOCK_FOLDER + "/large_dataset1.zip");
|
||||
List<String> original = readStringListFromInputStream(zip.getInputStream(zip.getEntry("ta")));
|
||||
List<String> revised = readStringListFromInputStream(zip.getInputStream(zip.getEntry("tb")));
|
||||
|
||||
Patch<String> patch = Patch.generate(original, revised, new HistogramDiff().diff(original, revised));
|
||||
|
||||
assertEquals(34, patch.getDeltas().size());
|
||||
|
||||
List<String> created = patch.applyTo(original);
|
||||
assertArrayEquals(revised.toArray(), created.toArray());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class MyersDiffTest {
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1Forward() throws DiffException {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(original, revised, new MyersDiff<String>().diff(original, revised));
|
||||
assertNotNull(patch);
|
||||
assertEquals(4, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [InsertDelta, position: 3, lines: [B]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
package com.github.difflib.text;
|
||||
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DiffRowGeneratorTest {
|
||||
|
||||
@Test
|
||||
public void testGenerator_Default() throws DiffException {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(Integer.MAX_VALUE) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerator_Default2() throws DiffException {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(0) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerator_InlineDiff() throws DiffException {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.columnWidth(Integer.MAX_VALUE) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertTrue(rows.get(0).getOldLine().indexOf("<span") > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerator_IgnoreWhitespaces() throws DiffException {
|
||||
String first = "anything \n \nother\nmore lines";
|
||||
String second = "anything\n\nother\nsome more lines";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.ignoreWhiteSpaces(true)
|
||||
.columnWidth(Integer.MAX_VALUE) // do not wrap
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(4, rows.size());
|
||||
assertEquals(rows.get(0).getTag(), DiffRow.Tag.EQUAL);
|
||||
assertEquals(rows.get(1).getTag(), DiffRow.Tag.EQUAL);
|
||||
assertEquals(rows.get(2).getTag(), DiffRow.Tag.EQUAL);
|
||||
assertEquals(rows.get(3).getTag(), DiffRow.Tag.CHANGE);
|
||||
}
|
||||
|
||||
private List<String> split(String content) {
|
||||
return Arrays.asList(content.split("\n"));
|
||||
}
|
||||
|
||||
private void print(List<DiffRow> diffRows) {
|
||||
for (DiffRow row : diffRows) {
|
||||
System.out.println(row);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithWordWrap() throws DiffException {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(5)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("[CHANGE,anyth<br/>ing ,anyth<br/>ing]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE, ,]", rows.get(1).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(2).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMerge() throws DiffException {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("[CHANGE,anything<span class=\"editOldInline\"> </span>,anything]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\"> </span>,]", rows.get(1).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(2).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMerge2() throws DiffException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"), Arrays.asList("ester"));
|
||||
print(rows);
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">T</span>est<span class=\"editNewInline\">er</span>,ester]", rows.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMerge3() throws DiffException {
|
||||
String first = "test\nanything \n \nother";
|
||||
String second = "anything\n\nother\ntest\ntest2";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(6, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">test,anything]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE,</span>anything<span class=\"editOldInline\"> </span>,]", rows.get(1).toString());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\"> </span>,]", rows.get(2).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(3).toString());
|
||||
assertEquals("[INSERT,<span class=\"editNewInline\">test</span>,test]", rows.get(4).toString());
|
||||
assertEquals("[INSERT,<span class=\"editNewInline\">test2</span>,test2]", rows.get(5).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMergeByWord4() throws DiffException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"), Arrays.asList("ester"));
|
||||
print(rows);
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">Test</span><span class=\"editNewInline\">ester</span>,ester]", rows.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorWithMergeByWord5() throws DiffException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.columnWidth(80)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test feature"), Arrays.asList("ester feature best"));
|
||||
print(rows);
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("[CHANGE,<span class=\"editOldInline\">Test</span><span class=\"editNewInline\">ester</span> <br/>feature<span class=\"editNewInline\"> best</span>,ester feature best]", rows.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitString() {
|
||||
List<String> list = DiffRowGenerator.splitStringPreserveDelimiter("test,test2", DiffRowGenerator.SPLIT_BY_WORD_PATTERN);
|
||||
assertEquals(3, list.size());
|
||||
assertEquals("[test, ,, test2]", list.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitString2() {
|
||||
List<String> list = DiffRowGenerator.splitStringPreserveDelimiter("test , test2", DiffRowGenerator.SPLIT_BY_WORD_PATTERN);
|
||||
System.out.println(list);
|
||||
assertEquals(5, list.size());
|
||||
assertEquals("[test, , ,, , test2]", list.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitString3() {
|
||||
List<String> list = DiffRowGenerator.splitStringPreserveDelimiter("test,test2,", DiffRowGenerator.SPLIT_BY_WORD_PATTERN);
|
||||
System.out.println(list);
|
||||
assertEquals(4, list.size());
|
||||
assertEquals("[test, ,, test2, ,]", list.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorExample1() throws DiffException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test senctence."),
|
||||
Arrays.asList("This is a test for diffutils."));
|
||||
|
||||
System.out.println(rows.get(0).getOldLine());
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("This is a test ~senctence~**for diffutils**.", rows.get(0).getOldLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorExample2() throws DiffException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test senctence.", "This is the second line.", "And here is the finish."),
|
||||
Arrays.asList("This is a test for diffutils.", "This is the second line."));
|
||||
|
||||
System.out.println("|original|new|");
|
||||
System.out.println("|--------|---|");
|
||||
for (DiffRow row : rows) {
|
||||
System.out.println("|" + row.getOldLine() + "|" + row.getNewLine() + "|");
|
||||
}
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("This is a test ~senctence~.", rows.get(0).getOldLine());
|
||||
assertEquals("This is a test **for diffutils**.", rows.get(0).getNewLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorUnchanged() throws DiffException {
|
||||
String first = "anything \n \nother";
|
||||
String second = "anything\n\nother";
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.columnWidth(5)
|
||||
.reportLinesUnchanged(true)
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
|
||||
print(rows);
|
||||
|
||||
assertEquals(3, rows.size());
|
||||
assertEquals("[CHANGE,anything ,anything]", rows.get(0).toString());
|
||||
assertEquals("[CHANGE, ,]", rows.get(1).toString());
|
||||
assertEquals("[EQUAL,other,other]", rows.get(2).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratorIssue14() throws DiffException {
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffBySplitter(line -> DiffRowGenerator.splitStringPreserveDelimiter(line, Pattern.compile(",")))
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("J. G. Feldstein, Chair"),
|
||||
Arrays.asList("T. P. Pastor, Chair"));
|
||||
|
||||
System.out.println(rows.get(0).getOldLine());
|
||||
|
||||
assertEquals(1, rows.size());
|
||||
assertEquals("~J. G. Feldstein~**T. P. Pastor**, Chair", rows.get(0).getOldLine());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user