160 Commits

Author SHA1 Message Date
Tobias Warneke
d5f7ffca5c [maven-release-plugin] prepare release java-diff-utils-parent-4.4 2019-11-06 22:58:41 +01:00
Tobias Warneke
f194a871b1 corrected pom.xml due to sonatype staging validation 2019-11-06 22:57:19 +01:00
Tobias Warneke
ab9908f3bc [maven-release-plugin] prepare for next development iteration 2019-11-06 22:54:17 +01:00
Tobias Warneke
8c7bb30b25 [maven-release-plugin] prepare release java-diff-utils-parent-4.3 2019-11-06 22:54:16 +01:00
Tobias Warneke
6c617ff949 [maven-release-plugin] prepare for next development iteration 2019-11-06 22:44:42 +01:00
Tobias Warneke
0d9f2ce62d [maven-release-plugin] prepare release java-diff-utils-parent-4.2 2019-11-06 22:44:40 +01:00
Tobias Warneke
ce4007b124 corrected pom.xml due to sonatype staging validation 2019-11-06 22:42:43 +01:00
Tobias Warneke
6e4e3910c1 [maven-release-plugin] prepare for next development iteration 2019-11-06 22:24:49 +01:00
Tobias Warneke
23a9c523c6 [maven-release-plugin] prepare release java-diff-utils-parent-4.1 2019-11-06 22:24:48 +01:00
Tobias Warneke
7d17c6088a Introduced a multi module java-diff-utils. The core project now has no more
external dependencies.
2019-11-02 22:03:28 +01:00
Tobias Warneke
17eced9367 Merge origin/master 2019-10-20 00:07:38 +02:00
Tobias Warneke
c534ebae98 fixes #57 2019-10-20 00:05:22 +02:00
David R. Smith
156f4f2986 Update README.md (#50)
Updated README.md with current Gradle artifact, as "compile" has been deprecated
2019-09-23 07:21:43 +02:00
rosta
c5b88e02db Proposal/issue 44 (#45)
* Correction of problem

It appears that the configuration reportLinesUnchanged has no effect
when showInlineDiffs is true. That is '<' and '>' characters are
converted to HTML entities regardless.

* Implement rawValues option

* Revert "Implement rawValues option"

This reverts commit d9c302cec8.
2019-09-21 14:05:24 +02:00
wumpz
f3ff104a9c fixes #33 2019-09-21 13:59:21 +02:00
Tobias Warneke
a24ceb930d Merge refactor-unified-diff-parser 2019-09-21 11:11:43 +02:00
Tobias Warneke
e82408e7a8 Merge origin/master 2019-09-21 11:10:57 +02:00
Tobias Warneke
93a5255007 fixes #46 2019-09-21 11:08:09 +02:00
Tobias Warneke
73263b41cf fixes #46 2019-09-21 11:03:21 +02:00
wumpz
a46d44643f 2019-09-20 14:35:29 +02:00
Tobias Warneke
fb3a8427bc 2019-09-04 23:46:58 +02:00
Tobias Warneke
5ab1882df8 2019-09-04 23:19:23 +02:00
Tobias Warneke
865a464906 2019-09-04 20:50:56 +02:00
Tobias Warneke
bb79a9b4fe 2019-08-14 23:53:55 +02:00
Tobias Warneke
4a5a39cf96 2019-08-14 23:39:30 +02:00
Tobias Warneke
a40c396678 2019-08-14 23:38:12 +02:00
Tobias
a3663002bb Update issue templates 2019-08-09 11:31:03 +02:00
Tobias
69cb8c520d Delete ISSUE_TEMPLATE.md 2019-08-09 11:28:27 +02:00
Tobias
0c75b43d88 Update .travis.yml
removed oracle jdk
2019-08-03 21:26:01 +02:00
wumpz
5cc9625275 fixes #43 2019-06-30 21:05:40 +02:00
wumpz
e520ee2f20 Merge master into unified-diff-parser
Conflicts:
	README.md
	pom.xml
2019-06-10 00:43:41 +02:00
wumpz
de227395cd Merge master into unified-diff-parser
Conflicts:
	README.md
	pom.xml
2019-06-10 00:41:27 +02:00
wumpz
ddd66e4554 Merge master into unified-diff-parser
Conflicts:
	README.md
	pom.xml
2019-06-10 00:35:09 +02:00
wumpz
4700647351 2019-06-10 00:19:52 +02:00
wumpz
4727557814 2019-06-07 00:30:17 +02:00
wumpz
630eed340b 2019-06-07 00:27:54 +02:00
wumpz
a018e9c432 2019-06-06 00:01:22 +02:00
wumpz
d30d9ca23a 2019-06-05 23:28:13 +02:00
wumpz
7d620c825c 2019-06-05 00:10:02 +02:00
wumpz
16cd9c6484 2019-06-05 00:05:40 +02:00
Tobias
30875cf6db Merge pull request #40 from Clashsoft/patch-1
Update Gradle Installation Snippet in README
2019-05-09 23:44:10 +02:00
wumpz
a34c185a44 2019-05-08 23:31:52 +02:00
wumpz
a8d968cc1d added some documentation 2019-05-07 09:57:52 +02:00
wumpz
89f2659dd7 fixes #41 2019-05-07 09:09:34 +02:00
Adrian Kunz
9704b62970 Update Gradle Installation
Updated the Group, Name, Version and Link in the Gradle Installation snippet.
2019-05-03 10:27:38 +02:00
wumpz
ecd834f3f5 2019-04-30 23:55:38 +02:00
wumpz
8c6679e295 2019-04-15 00:51:14 +02:00
wumpz
4c1a0bc072 2019-04-15 00:17:53 +02:00
Tobias
fd64d15ab0 Merge pull request #38 from 0xflotus/patch-2
fixed Algorithms and Ascii
2019-04-02 20:50:17 +02:00
0xflotus
13f2f5ede1 fixed Algorithms and Ascii 2019-04-02 18:00:59 +02:00
Tobias
1c3a2b598e Merge pull request #35 from koppor/add-changelog-md
Move CHANGELOG to separate file CHANGELOG.md
2019-03-31 21:03:11 +02:00
Tobias
4719139448 Merge pull request #36 from koppor/improve-readme.md
Fix linting issues in README.md
2019-03-31 21:01:49 +02:00
Tobias
b5eb632a4d Merge pull request #37 from koppor/refine-gitignore
Add support for IntelliJ to .gitignore
2019-03-31 21:00:25 +02:00
Oliver Kopp
6321d5327c Add support for IntelliJ to .gitignore 2019-03-31 14:33:54 +02:00
Oliver Kopp
a4bb85bab1 Fix linting issues in README.md 2019-03-31 14:29:09 +02:00
Oliver Kopp
535ecf3e2a Move CHANGELOG to separte file CHANGELOG.md
For more information on that format see http://keepachangelog.com/
2019-03-31 14:26:26 +02:00
wumpz
61a21cbca9 2019-03-26 21:36:31 +01:00
wumpz
4a83032d7e 2019-03-26 21:14:54 +01:00
wumpz
8c86e0f8d7 upgraded checkstyle plugin (security alert from github) 2019-03-26 07:58:25 +01:00
wumpz
983ec680f7 2019-03-18 22:36:49 +01:00
wumpz
05b5d80d48 2019-03-18 22:34:08 +01:00
wumpz
d2355a8435 2019-03-12 00:15:51 +01:00
wumpz
55e4867e88 2019-03-10 23:36:16 +01:00
wumpz
253a94becb 2019-03-10 19:24:09 +01:00
wumpz
a523ba3a14 2019-03-10 19:24:03 +01:00
wumpz
361c27d5e7 2019-03-06 01:54:39 +01:00
wumpz
c917f77bbf 2019-03-06 01:45:39 +01:00
wumpz
4caf63c193 2019-03-06 01:34:39 +01:00
wumpz
c0a1a3777c first start unified diff 2019-02-28 23:59:26 +01:00
Tobias
2787a2db6c Merge pull request #30 from skitt/cleanups
Cleanups
2019-02-08 11:40:54 +01:00
Stephen Kitt
e8c015a2ec Fix Javadoc errors
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:31 +01:00
Stephen Kitt
765dc29386 Use List.sort instead of Collections.sort
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:31 +01:00
Stephen Kitt
a312ec14ea Use foreach loop
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:31 +01:00
Stephen Kitt
3443d55a19 Drop redundant casts
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:31 +01:00
Stephen Kitt
b41e2d5b5a Use assertEquals for comparison
... instead of assertTrue(a == b)

Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:31 +01:00
Stephen Kitt
47c6e9b417 Drop unnecessary Integer.toString
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:30 +01:00
Stephen Kitt
2d116d8c54 Use String.join instead of streaming/collecting
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-08 09:20:30 +01:00
Stephen Kitt
de2f19497a Remove unused DiffException declarations
Signed-off-by: Stephen Kitt <skitt@redhat.com>
2019-02-07 18:51:58 +01:00
Tobias
5dd05c480d Merge pull request #29 from heisluft/master
[Minor] Exchange "0 += 1" for "0 = 1" in UnifiedDiffUtils
2018-12-08 19:53:42 +01:00
heisluft
fc1e247de2 Exchange "0 += 1" for "0 = 1" 2018-12-08 14:56:40 +01:00
Tobias
ab05a8bdb4 Update README.md 2018-11-23 08:19:56 +01:00
Tobias
5fe7e58f76 Update README.md 2018-11-23 08:16:05 +01:00
Tobias
785c368f01 Update README.md 2018-11-23 08:15:08 +01:00
wumpz
c9a2c9e7f0 [maven-release-plugin] prepare for next development iteration 2018-11-22 21:50:54 +01:00
wumpz
4bab820483 [maven-release-plugin] prepare release java-diff-utils-4.0 2018-11-22 21:50:52 +01:00
wumpz
4fe80bdf1e changed readme to new home 2018-11-16 00:30:34 +01:00
wumpz
005ba349f8 2018-11-15 17:32:08 +01:00
wumpz
0fbbb53b77 2018-11-12 18:10:49 +01:00
wumpz
d5fbf5022e changed groupid, artifactid
moved to new organistion java-diff-utils
switched to version 4.0-SNAPSHOT
2018-11-04 22:56:17 +01:00
Tobias
2c85597238 Merge pull request #28 from koppor/fix-headers
Reformat Apache 2.0 headers (remove #%L things)
2018-10-28 18:09:06 +01:00
Tobias
f88ce15ff8 Merge pull request #27 from koppor/use-objects-hash
Use Objects.hash() instead of custom hashCode() method
2018-10-28 18:08:50 +01:00
Oliver Kopp
30a23c00d1 Reformat Apache 2.0 headers (remove #%L things) 2018-10-28 17:25:20 +01:00
Oliver Kopp
306f92684f Use Objects.hash() instead of custom hashCode() method 2018-10-28 17:13:03 +01:00
wumpz
d4f114226d fixes #26 2018-10-18 21:52:57 +02:00
wumpz
65183197c5 [maven-release-plugin] prepare for next development iteration 2018-10-18 21:39:22 +02:00
wumpz
5c33149e2a [maven-release-plugin] prepare release diffutils-3.0 2018-10-18 21:39:21 +02:00
Tobias
b273da278e Update README.md 2018-10-10 09:54:45 +02:00
wumpz
2671949b92 2018-09-13 15:32:14 +02:00
Tobias
5a32ede79f Merge pull request #25 from benelog/refactor-regex
Refactor to reuse java.util.regex.Pattern
2018-09-13 15:17:44 +02:00
Sanghyuk Jung
5dc489a4ef Refactor to reuse java.util.regex.Pattern 2018-09-13 17:31:05 +09:00
wumpz
f2ab70afc4 fixes #22 2018-08-03 10:55:07 +02:00
wumpz
c410422860 fixes #22 2018-08-03 10:51:56 +02:00
wumpz
1161243bc2 2018-08-03 09:23:04 +02:00
wumpz
f0fe7a2137 Merge origin/master 2018-08-02 11:46:07 +02:00
wumpz
d506d62a91 added a default method for computeDiff from arrays 2018-07-02 00:44:53 +02:00
wumpz
33f2d744ab brought back diffutils to life 2018-06-28 22:42:06 +02:00
wumpz
696d22bd94 Removed DiffAlgorithm.java and Delta.java due to licensing issues. The originals were Apache 1.1. Now we start a clean room implementation of those two files. 2018-06-28 21:46:18 +02:00
wumpz
42780b18a8 2018-06-27 22:31:42 +02:00
wumpz
13a1522d46 Merge origin/master
Conflicts:
	README.md
2018-06-17 23:34:02 +02:00
wumpz
d12b13da41 fixes #21 2018-06-17 23:32:43 +02:00
wumpz
c8f0624a7b jdk8 2018-06-13 23:19:43 +02:00
wumpz
54bf402a9a 2018-06-13 15:33:04 +02:00
Tobias
3a87d24632 Update README.md 2018-05-16 23:04:12 +02:00
Tobias
67b26e5cab Update README.md 2018-05-09 12:06:22 +02:00
Tobias
592ff058c1 Update README.md 2018-05-09 12:04:49 +02:00
wumpz
553ef27e0c Merge origin/master 2018-05-07 01:35:39 +02:00
wumpz
d1c22e7243 fixes #19 2018-05-07 01:34:22 +02:00
wumpz
0d15097947 some renaming 2018-04-10 07:32:44 +02:00
wumpz
dbfdffd626 Merge origin/master 2018-03-17 00:57:38 +01:00
wumpz
33a0b58299 introduces test for issue #15 2018-03-17 00:57:20 +01:00
Tobias
db114a2c2a Update README.md 2018-03-15 15:10:52 +01:00
Tobias
c001819855 Update README.md 2018-03-15 15:08:38 +01:00
Tobias
c6e4059de4 Update README.md 2018-03-05 10:01:59 +01:00
Tobias
653d1f9153 Update README.md 2018-03-05 09:45:57 +01:00
Tobias
1214f4cf23 Create ISSUE_TEMPLATE.md 2018-02-08 08:08:06 +01:00
Tobias
04832c7c9a Set theme jekyll-theme-minimal 2017-12-27 20:55:59 +01:00
Tobias
d498a41dd3 Delete _config.yml 2017-12-27 20:55:26 +01:00
Tobias
a998d8d98b Set theme jekyll-theme-minimal 2017-12-27 20:52:11 +01:00
Tobias
91ddcccd1e Set theme jekyll-theme-minimal 2017-12-22 10:25:53 +01:00
Tobias
005f95ab9d Delete _config.yml 2017-12-22 10:25:15 +01:00
Tobias
1914de7e5c Set theme jekyll-theme-minimal 2017-12-22 10:24:59 +01:00
Tobias
e630c7975a Set theme jekyll-theme-minimal 2017-12-22 10:22:13 +01:00
Tobias
10c17b4287 Set theme jekyll-theme-hacker 2017-12-22 10:20:58 +01:00
Tobias
08d4914a8b Delete docs.txt 2017-12-22 10:20:18 +01:00
Tobias
df3ec97df4 Delete _config.yml 2017-12-22 10:20:05 +01:00
Tobias
8c242a42ef Set theme jekyll-theme-cayman 2017-12-22 10:19:14 +01:00
wumpz
05de2df99d introduced docs folder 2017-12-22 10:11:35 +01:00
Tobias
0eb7b6c34f Set theme jekyll-theme-minimal 2017-12-22 09:04:38 +01:00
Tobias
5e0d398c53 Set theme jekyll-theme-hacker 2017-12-22 09:02:33 +01:00
Tobias
829567bace Create LICENSE 2017-12-22 08:24:51 +01:00
Tobias
02c97e4691 Update README.md 2017-12-01 09:12:42 +01:00
wumpz
4933ca5200 2017-11-09 23:02:00 +01:00
wumpz
a65ffd95a9 2017-11-09 22:59:29 +01:00
wumpz
dcf66dfadc [maven-release-plugin] prepare for next development iteration 2017-11-09 22:47:30 +01:00
wumpz
244e7e7fd8 [maven-release-plugin] prepare release diffutils-2.2 2017-11-09 22:47:30 +01:00
wumpz
424cfcefd7 2017-11-09 22:45:47 +01:00
wumpz
15af24ac02 [maven-release-plugin] prepare for next development iteration 2017-11-09 22:38:40 +01:00
wumpz
0a2053f71a [maven-release-plugin] prepare release diffutils-2.1 2017-11-09 22:38:40 +01:00
wumpz
4f6b1839f8 2017-11-09 22:24:46 +01:00
wumpz
5764356be2 2017-11-09 22:12:57 +01:00
wumpz
4f6f8dbcf2 fixes #14 2017-11-09 14:34:50 +01:00
wumpz
573460df9c preparing maven central release 2017-11-09 12:33:27 +01:00
wumpz
d2a432059d preparing maven central release 2017-11-09 12:30:47 +01:00
wumpz
90eaf2e134 starting corrections for maven central release 2017-11-08 08:29:59 +01:00
wumpz
e6fa5938a9 included checkstyle source code conventions 2017-10-25 08:49:20 +02:00
wumpz
88146c6afb make columnwith 0, meaning no text wrap, the standard 2017-09-28 13:25:54 +02:00
wumpz
aed1d31c2b 2017-08-30 13:46:55 +02:00
wumpz
5d5218ba30 fixes #11 2017-08-18 14:50:32 +02:00
wumpz
1107f43f36 fixes #11 2017-08-18 14:48:35 +02:00
wumpz
6c91ef68df [maven-release-plugin] prepare for next development iteration 2017-08-14 09:21:33 +02:00
81 changed files with 4208 additions and 2202 deletions

24
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View 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]

6
.gitignore vendored
View File

@@ -1,2 +1,4 @@
/target/
/nbproject/
.idea/
build/
nbproject/
target/

View File

@@ -1,6 +1,7 @@
language: java
jdk:
- oraclejdk8
- openjdk8
- openjdk11
after_success:
- mvn clean
- mvn clean

85
CHANGELOG.md Normal file
View File

@@ -0,0 +1,85 @@
# 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
* 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-4.0...HEAD
[4.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diff-utils-3.0...java-diff-utils-4.0
[3.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diff-utils-2.2...diff-utils-3.0
[2.2]: https://github.com/java-diff-utils/java-diff-utils/compare/diff-utils-2.0...diff-utils-2.2

201
LICENSE Normal file
View 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.

View File

@@ -1,18 +1,22 @@
# java-diff-utils
## Status ##
[![Build Status](https://travis-ci.org/wumpz/java-diff-utils.svg?branch=master)](https://travis-ci.org/wumpz/java-diff-utils) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/7eba77f10bed4c2a8d08ac8dc8da4a86)](https://www.codacy.com/app/wumpz/java-diff-utils?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=wumpz/java-diff-utils&amp;utm_campaign=Badge_Grade)
## Status
[![Build Status](https://travis-ci.org/java-diff-utils/java-diff-utils.svg?branch=master)](https://travis-ci.org/java-diff-utils/java-diff-utils)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7eba77f10bed4c2a8d08ac8dc8da4a86)](https://www.codacy.com/app/wumpz/java-diff-utils?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=java-diff-utils/java-diff-utils&amp;utm_campaign=Badge_Grade)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.java-diff-utils/java-diff-utils/badge.svg)](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 ##
## Examples
Look [here](https://github.com/wumpz/java-diff-utils/wiki) to find more helpful informations and 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 +24,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,52 +32,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.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
### To Install ###
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.
**This jar is not yet to get at maven central.**
```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<>());
}
```
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
Just add the code below to your maven dependencies:
```
```xml
<dependency>
<groupId>com.github.java-diff-utils</groupId>
<artifactId>diffutils</artifactId>
   <version>2.0-SNAPSHOT</version>
<groupId>io.github.java-diff-utils</groupId>
<artifactId>java-diff-utils</artifactId>
<version>4.0</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.0"
```

1
_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-minimal

View 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.compile.on.save>none</netbeans.compile.on.save>
<netbeans.hint.jdkPlatform>JDK_1.8</netbeans.hint.jdkPlatform>
</properties>
</project-shared-configuration>

View File

@@ -0,0 +1,59 @@
<?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.4</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>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>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>java-diff-utils</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -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,34 +28,40 @@ 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;
DeltaType type = DeltaType.EQUAL;
switch (edit.getType()) {
case DELETE:
type = DeltaType.DELETE;
type = DeltaType.DELETE;
break;
case INSERT:
type = DeltaType.INSERT;
type = DeltaType.INSERT;
break;
case REPLACE:
type = DeltaType.CHANGE;
type = DeltaType.CHANGE;
break;
}
patch.add(new Change(type,edit.getBeginA(), edit.getEndA(), edit.getBeginB(), edit.getEndB()));
patch.add(new Change(type, edit.getBeginA(), edit.getEndA(), edit.getBeginB(), edit.getEndB()));
}
if (progress != null) {
progress.diffEnd();
}
return patch;
}
@@ -63,8 +69,17 @@ public class HistogramDiff<T> implements DiffAlgorithm<T> {
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));
}

View File

@@ -15,44 +15,40 @@
*/
package com.github.difflib.algorithm.jgit;
import com.github.difflib.algorithm.jgit.HistogramDiff;
import static com.github.difflib.DiffUtilsTest.readStringListFromInputStream;
import com.github.difflib.TestConstants;
import com.github.difflib.algorithm.DiffException;
import com.github.difflib.algorithm.DiffAlgorithmListener;
import com.github.difflib.patch.Patch;
import com.github.difflib.patch.PatchFailedException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
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;
import static org.junit.Assert.*;
/**
*
* @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() {
}
@@ -61,16 +57,50 @@ public class HistogramDiffTest {
* 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));
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(17, logdata.size());
}
}

View File

@@ -15,61 +15,88 @@
*/
package com.github.difflib.algorithm.jgit;
import com.github.difflib.algorithm.jgit.HistogramDiff;
import static com.github.difflib.DiffUtilsTest.readStringListFromInputStream;
import com.github.difflib.TestConstants;
import com.github.difflib.algorithm.DiffException;
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.util.Arrays;
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 org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @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");
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")));
Patch<String> patch = Patch.generate(original, revised, new HistogramDiff().diff(original, revised));
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());
}
}
}

View File

@@ -1,29 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/junit.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" />
</component>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/junit.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" />
</component>
</module>

60
java-diff-utils/pom.xml Normal file
View File

@@ -0,0 +1,60 @@
<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.4</version>
</parent>
<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.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.11.1</version>
<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.java-diff-utils</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,118 +1,129 @@
/*-
* #%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.DiffAlgorithmI;
import com.github.difflib.algorithm.DiffAlgorithmListener;
import com.github.difflib.algorithm.DiffException;
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;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
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 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}.
* @throws com.github.difflib.algorithm.DiffException
*/
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) throws DiffException {
return DiffUtils.diff(original, revised, new MyersDiff<>(), progress);
}
public static <T> Patch<T> diff(List<T> original, List<T> revised) throws DiffException {
return DiffUtils.diff(original, revised, new MyersDiff<>(), null);
}
/**
* 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) throws DiffException {
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) throws DiffException {
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<>());
}
/**
* 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.
* @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 {
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));
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) throws DiffException {
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.computeDiff(original, revised, progress));
}
/**
* 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) throws DiffException {
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.
* 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 {
LinkedList<String> origList = new LinkedList<>();
LinkedList<String> revList = new LinkedList<>();
List<String> origList = new ArrayList<>();
List<String> revList = new ArrayList<>();
for (Character character : original.toCharArray()) {
origList.add(character.toString());
}
@@ -120,9 +131,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;
}
@@ -131,7 +142,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));
}
/**

View File

@@ -17,7 +17,7 @@ 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;
@@ -29,6 +29,7 @@ import java.util.regex.Pattern;
* @author toben
*/
public final class UnifiedDiffUtils {
private static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern
.compile("^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@$");
@@ -82,10 +83,10 @@ public final class UnifiedDiffUtils {
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) {
@@ -124,42 +125,42 @@ public final class UnifiedDiffUtils {
return patch;
}
/**
* 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("--- " + originalFileName);
ret.add("+++ " + revisedFileName);
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
@@ -169,9 +170,9 @@ 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,
@@ -195,10 +196,9 @@ public final class UnifiedDiffUtils {
}
return new ArrayList<>();
}
/**
* 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 +207,33 @@ 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) {
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);
AbstractDelta<String> curDelta = deltas.get(0);
// NOTE: +1 to overcome the 0-offset Position
int origStart = curDelta.getOriginal().getPosition() + 1 - contextSize;
int 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 +241,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 +257,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 +275,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(",");
@@ -289,7 +289,7 @@ public final class UnifiedDiffUtils {
return buffer;
}
/**
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter
*
@@ -297,17 +297,17 @@ 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;
}
private UnifiedDiffUtils() {
}
}

View File

@@ -19,9 +19,10 @@ import com.github.difflib.patch.DeltaType;
/**
*
* @author toben
* @author <a href="t.warneke@gmx.net">Tobias Warneke</a>
*/
public class Change {
public final DeltaType deltaType;
public final int startOriginal;
public final int endOriginal;

View File

@@ -0,0 +1,51 @@
/*
* 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)
*/
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
* @throws DiffException
*/
List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) throws DiffException;
/**
* Simple extension to compute a changeset using arrays.
*
* @param source
* @param target
* @param progress
* @return
* @throws com.github.difflib.algorithm.DiffException
*/
default List<Change> computeDiff(T[] source, T[] target, DiffAlgorithmListener progress) throws DiffException {
return computeDiff(Arrays.asList(source), Arrays.asList(target), progress);
}
}

View File

@@ -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();
}

View File

@@ -0,0 +1,28 @@
/*
* 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.algorithm;
public class DiffException extends Exception {
private static final long serialVersionUID = 1L;
public DiffException() {
}
public DiffException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.algorithm;
/**
* Thrown whenever the differencing engine cannot produce the differences between two revisions of ta text.
*
* @see com.github.difflib.algorithm.myers.MyersDiff
* @see DiffAlgorithmI
*/
public class DifferentiationFailedException extends DiffException {
private static final long serialVersionUID = 1L;
public DifferentiationFailedException() {
}
public DifferentiationFailedException(String msg) {
super(msg);
}
}

View File

@@ -1,28 +1,25 @@
/*-
* #%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.DifferentiationFailedException;
import com.github.difflib.algorithm.DiffAlgorithm;
import com.github.difflib.algorithm.DiffAlgorithmI;
import com.github.difflib.algorithm.DiffAlgorithmListener;
import com.github.difflib.algorithm.DiffException;
import com.github.difflib.algorithm.DifferentiationFailedException;
import com.github.difflib.patch.DeltaType;
import com.github.difflib.patch.Patch;
import java.util.ArrayList;
@@ -33,18 +30,16 @@ import java.util.function.BiPredicate;
/**
* A clean-room implementation of Eugene Myers greedy differencing algorithm.
*/
public final class MyersDiff<T> implements DiffAlgorithm<T> {
private final BiPredicate<T,T> DEFAULT_EQUALIZER = Object::equals;
private final BiPredicate<T,T> equalizer;
public final class MyersDiff<T> implements DiffAlgorithmI<T> {
private final BiPredicate<T, T> DEFAULT_EQUALIZER = Object::equals;
private final BiPredicate<T, T> equalizer;
public MyersDiff() {
equalizer = DEFAULT_EQUALIZER;
}
public MyersDiff(final BiPredicate<T,T> equalizer) {
public MyersDiff(final BiPredicate<T, T> equalizer) {
Objects.requireNonNull(equalizer, "equalizer must not be null");
this.equalizer = equalizer;
}
@@ -55,25 +50,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) throws DiffException {
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)
private PathNode buildPath(final List<T> orig, final List<T> rev, DiffAlgorithmListener progress)
throws DifferentiationFailedException {
Objects.requireNonNull(orig, "original sequence is null");
Objects.requireNonNull(rev, "revised sequence is null");
@@ -89,6 +90,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;
@@ -134,12 +138,12 @@ public final class MyersDiff<T> implements DiffAlgorithm<T> {
/**
* 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");
@@ -169,18 +173,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;
}

View File

@@ -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 {
@@ -44,7 +36,7 @@ public final class PathNode {
public final PathNode prev;
public final boolean snake;
public final boolean bootstrap;
/**
@@ -61,7 +53,7 @@ public final class PathNode {
if (snake) {
this.prev = prev;
} else {
this.prev = (prev == null ? null : prev.previousSnake());
this.prev = prev == null ? null : prev.previousSnake();
}
this.snake = snake;
}
@@ -82,11 +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 path is reached.
* 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()) {
@@ -107,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;
}

View File

@@ -0,0 +1,92 @@
/*
* 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);
@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;
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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() + "]";
}
}

View File

@@ -1,26 +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.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
@@ -33,7 +31,7 @@ import java.util.List;
* </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> {
@@ -48,7 +46,7 @@ public final class Chunk<T> {
*/
public Chunk(int position, List<T> lines) {
this.position = position;
this.lines = lines;
this.lines = new ArrayList<>(lines);
}
/**
@@ -66,6 +64,7 @@ public final class Chunk<T> {
* 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()) {
@@ -108,26 +107,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) {

View File

@@ -0,0 +1,62 @@
/*
* 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() + "]";
}
}

View File

@@ -31,8 +31,7 @@ public enum DeltaType {
/**
* An insert into the original.
*/
INSERT,
INSERT,
/**
* An do nothing.
*/

View File

@@ -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);
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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() + "]";
}
}

View File

@@ -19,13 +19,9 @@ limitations under the License.
*/
package com.github.difflib.patch;
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.LinkedList;
import com.github.difflib.algorithm.Change;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
@@ -33,11 +29,19 @@ 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 = new LinkedList<>();
private final List<AbstractDelta<T>> deltas;
public Patch() {
this(10);
}
public Patch(int estimatedPatchSize) {
deltas = new ArrayList<>(estimatedPatchSize);
}
/**
* Apply this patch to the given target
@@ -46,10 +50,10 @@ public final class Patch<T> {
* @throws PatchFailedException if can't apply patch
*/
public List<T> applyTo(List<T> target) throws PatchFailedException {
List<T> result = new LinkedList<>(target);
ListIterator<Delta<T>> it = getDeltas().listIterator(deltas.size());
List<T> result = new ArrayList<>(target);
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;
@@ -62,10 +66,10 @@ public final class Patch<T> {
* @return the restored text
*/
public List<T> restore(List<T> target) {
List<T> result = new LinkedList<>(target);
ListIterator<Delta<T>> it = getDeltas().listIterator(deltas.size());
List<T> result = new ArrayList<>(target);
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;
@@ -76,17 +80,17 @@ 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);
}
/**
/**
* Get the list of computed deltas
*
* @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;
}
@@ -94,9 +98,9 @@ public final class Patch<T> {
public String toString() {
return "Patch{" + "deltas=" + deltas + '}';
}
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> changes) {
Patch<T> patch = new Patch<>();
Patch<T> patch = new Patch<>(changes.size());
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)));

View File

@@ -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);
}
}

View File

@@ -1,29 +1,25 @@
/*-
* #%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
* Describes the diff row in form [tag, oldLine, newLine) for showing the difference between two texts
*
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/
@@ -71,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) {

View File

@@ -1,30 +1,26 @@
/*-
* #%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.AbstractDelta;
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.InsertDelta;
import com.github.difflib.patch.Patch;
import com.github.difflib.text.DiffRow.Tag;
@@ -33,34 +29,332 @@ 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; ...
*
* For instantiating the DiffRowGenerator you should use the its builder. Like in example <code>
* DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true).
* ignoreWhiteSpaces(true).columnWidth(100).build();
* ignoreWhiteSpaces(true).columnWidth(100).build();
* </code>
*/
public class DiffRowGenerator {
public final class DiffRowGenerator {
public static final BiPredicate<String,String> IGNORE_WHITESPACE_EQUALIZER = (original, revised)
-> original.trim().replaceAll("\\s+", " ").equals(revised.trim().replaceAll("\\s+", " "));
public static final BiPredicate<String,String> DEFAULT_EQUALIZER = Object::equals;
private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+|[,.\\[\\](){}/\\\\*+\\-#]");
private final boolean showInlineDiffs;
private final boolean ignoreWhiteSpaces;
private final Function<Boolean, String> oldTag;
private final Function<Boolean, String> newTag;
private final boolean inlineDiffByWord;
public static final BiPredicate<String, String> DEFAULT_EQUALIZER = Object::equals;
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.
*/
public static final Function<String, List<String>> SPLITTER_BY_CHARACTER = line -> {
List<String> list = new ArrayList<>(line.length());
for (Character character : line.toCharArray()) {
list.add(character.toString());
}
return list;
};
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, Function<Boolean, String> tagGenerator) {
int endPos = endPosition;
while (endPos >= startPosition) {
//search position for end tag
while (endPos > startPosition) {
if (!"\n".equals(sequence.get(endPos - 1))) {
break;
}
endPos--;
}
if (endPos == startPosition) {
break;
}
sequence.add(endPos, tagGenerator.apply(false));
endPos--;
//search position for end tag
while (endPos > startPosition) {
if ("\n".equals(sequence.get(endPos - 1))) {
break;
}
endPos--;
}
sequence.add(endPos, tagGenerator.apply(true));
endPos--;
}
// sequence.add(endPosition, tagGenerator.apply(false));
// sequence.add(startPosition, tagGenerator.apply(true));
}
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 Function<Boolean, String> newTag;
private final Function<Boolean, String> oldTag;
private final boolean reportLinesUnchanged;
private final Function<String, String> lineNormalizer;
private final boolean showInlineDiffs;
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;
lineNormalizer = builder.lineNormalizer;
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) throws DiffException {
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) throws DiffException {
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 instanceof InsertDelta) {
endPos = orig.last() + 1;
for (String line : rev.getLines()) {
diffRows.add(buildDiffRow(Tag.INSERT, "", line));
}
continue;
}
// Deleted DiffRow
if (delta instanceof DeleteDelta) {
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(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));
}
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) throws DiffException {
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).getDeltas();
Collections.reverse(inlineDeltas);
for (AbstractDelta<String> inlineDelta : inlineDeltas) {
Chunk<String> inlineOrig = inlineDelta.getSource();
Chunk<String> inlineRev = inlineDelta.getTarget();
if (inlineDelta instanceof DeleteDelta) {
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
.getPosition()
+ inlineOrig.size(), 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(), newTag);
} else {
wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
+ inlineRev.size(), 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(), newTag);
} else {
wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
+ inlineRev.size(), newTag);
}
wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
.getPosition()
+ inlineOrig.size(), 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;
}
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.
@@ -76,9 +370,11 @@ public class DiffRowGenerator {
private Function<Boolean, String> oldTag = f -> f ? "<span class=\"editOldInline\">" : "</span>";
private Function<Boolean, String> newTag = f -> f ? "<span class=\"editNewInline\">" : "</span>";
private int columnWidth = 80;
private int columnWidth = 0;
private boolean mergeOriginalRevised = false;
private boolean inlineDiffByWord = false;
private boolean reportLinesUnchanged = false;
private Function<String, List<String>> inlineDiffSplitter = SPLITTER_BY_CHARACTER;
private Function<String, String> lineNormalizer = LINE_NORMALIZER_FOR_HTML;
private Builder() {
}
@@ -105,10 +401,22 @@ public class DiffRowGenerator {
return this;
}
/**
* 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
*/
public Builder reportLinesUnchanged(final boolean val) {
reportLinesUnchanged = val;
return this;
}
/**
* 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(Function<Boolean, String> generator) {
@@ -128,13 +436,13 @@ public class DiffRowGenerator {
}
/**
* Set the column with of generated lines of original and revised texts.
* Set the column width of generated lines of original and revised texts.
*
* @param width the width to set. Making it < 0 doesn't have any sense. Default 80. @return
* builder with config ured ignoreBlankLines parameter
* @param width the width to set. Making it < 0 doesn't have any sense. Default 80. @return builder with config
* ured ignoreBlankLines parameter
*/
public Builder columnWidth(int width) {
if (width > 0) {
if (width >= 0) {
columnWidth = width;
}
return this;
@@ -150,8 +458,7 @@ 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
@@ -162,239 +469,41 @@ 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) {
this.inlineDiffByWord = inlineDiffByWord;
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;
}
/**
* By default DiffRowGenerator preprocesses lines for HTML output. Tabs and special HTML characters like "&lt;"
* 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;
}
}
public static Builder create() {
return new Builder();
}
private DiffRowGenerator(Builder builder) {
showInlineDiffs = builder.showInlineDiffs;
ignoreWhiteSpaces = builder.ignoreWhiteSpaces;
oldTag = builder.oldTag;
newTag = builder.newTag;
columnWidth = builder.columnWidth;
mergeOriginalRevised = builder.mergeOriginalRevised;
inlineDiffByWord = builder.inlineDiffByWord;
equalizer = ignoreWhiteSpaces?IGNORE_WHITESPACE_EQUALIZER:DEFAULT_EQUALIZER;
}
/**
* 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 DiffRow buildDiffRow(Tag type, String orgline, String newline) {
String wrapOrg = StringUtils.wrapText(StringUtils.normalize(orgline), columnWidth);
if (Tag.DELETE == type) {
if (mergeOriginalRevised || showInlineDiffs) {
wrapOrg = oldTag.apply(true) + wrapOrg + oldTag.apply(false);
}
}
String wrapNew = StringUtils.wrapText(StringUtils.normalize(newline), columnWidth);
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;
if (inlineDiffByWord) {
origList = splitStringPreserveDelimiter(String.join("\n", orig));
revList = splitStringPreserveDelimiter(String.join("\n", rev));
} else {
origList = new LinkedList<>();
revList = new LinkedList<>();
for (Character character : String.join("\n", orig).toCharArray()) {
origList.add(character.toString());
}
for (Character character : String.join("\n", rev).toCharArray()) {
revList.add(character.toString());
}
}
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) {
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;
}
}

View File

@@ -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))
@@ -58,8 +48,11 @@ final class StringUtils {
* @return the wrapped text
*/
public static String wrapText(String line, int columnWidth) {
if (columnWidth <= 0) {
throw new IllegalArgumentException("columnWidth may not be less or equal 0");
if (columnWidth < 0) {
throw new IllegalArgumentException("columnWidth may not be less 0");
}
if (columnWidth == 0) {
return line;
}
int length = line.length();
int delimiter = "<br/>".length();

View File

@@ -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;
}
}

View File

@@ -0,0 +1,95 @@
/*
* 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 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;
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,323 @@
/*
* 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,})");
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 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.INFO, "header parsing");
String line = null;
while (READER.ready()) {
line = READER.readLine();
LOG.log(Level.INFO, "parsing line {0}", line);
if (DIFF_COMMAND.validLine(line) || INDEX.validLine(line)
|| FROM_FILE.validLine(line) || TO_FILE.validLine(line)) {
break;
} else {
headerTxt += line + "\n";
}
}
if (!"".equals(headerTxt)) {
data.setHeader(headerTxt);
}
while (line != null) {
if (!CHUNK.validLine(line)) {
initFileIfNecessary();
while (!CHUNK.validLine(line)) {
if (processLine(line, DIFF_COMMAND, INDEX, FROM_FILE, TO_FILE) == false) {
throw new UnifiedDiffParserException("expected file start line not found");
}
line = READER.readLine();
}
}
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) {
finalizeChunk();
break;
}
}
line = READER.readLine();
if (line == null || line.startsWith("--")) {
break;
}
}
if (READER.ready()) {
String tailTxt = "";
while (READER.ready()) {
tailTxt += READER.readLine() + "\n";
}
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 {
for (UnifiedDiffLine rule : rules) {
if (rule.processLine(line)) {
LOG.info(" >>> processed rule " + rule.toString());
return true;
}
}
LOG.info(" >>> 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.INFO, "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.INFO, "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 String extractFileName(String _line) {
Matcher matcher = TIMESTAMP_REGEXP.matcher(_line);
String line = _line;
if (matcher.find()) {
line = line.substring(1, matcher.start());
}
return line.substring(4).replaceFirst("^(a|b)\\/", "")
.replace(TIMESTAMP_REGEXP.toString(), "").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;
}
}

View File

@@ -0,0 +1,201 @@
/*
* 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.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 {
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 {
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());
}
if (file.getFromFile() != null) {
writer.accept("--- " + 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);
deltas.clear();
deltas.add(nextDelta);
}
delta = nextDelta;
}
}
// don't forget to process the last set of Deltas
processDeltas(writer, originalLines, deltas, contextSize);
}
}
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) {
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);
// NOTE: +1 to overcome the 0-offset Position
int 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++) { //
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++) {
// 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);
}
}
}

View File

@@ -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;

View File

@@ -1,11 +1,10 @@
package com.github.difflib;
import com.github.difflib.DiffUtils;
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.InsertDelta;
import com.github.difflib.patch.Patch;
import java.io.BufferedReader;
@@ -34,10 +33,10 @@ public class DiffUtilsTest {
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
@@ -46,10 +45,10 @@ public class DiffUtilsTest {
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
@@ -60,10 +59,10 @@ public class DiffUtilsTest {
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
@@ -78,7 +77,7 @@ public class DiffUtilsTest {
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);
}
@@ -87,9 +86,9 @@ public class DiffUtilsTest {
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
@@ -97,12 +96,12 @@ public class DiffUtilsTest {
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
@@ -112,7 +111,7 @@ public class DiffUtilsTest {
final Patch<Integer> patch = DiffUtils.diff(original, revised);
for (Delta delta : patch.getDeltas()) {
for (AbstractDelta delta : patch.getDeltas()) {
System.out.println(delta);
}
@@ -138,25 +137,25 @@ public class DiffUtilsTest {
@Ignore
public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException, DiffException {
ZipFile zip = new ZipFile(TestConstants.MOCK_FOLDER + "/large_dataset1.zip");
Patch<String> patch = DiffUtils.diff(
readStringListFromInputStream(zip.getInputStream(zip.getEntry("ta"))),
readStringListFromInputStream(zip.getInputStream(zip.getEntry("ta"))),
readStringListFromInputStream(zip.getInputStream(zip.getEntry("tb"))));
assertEquals(1, patch.getDeltas().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());
}
}
@Test
public void testDiffMyersExample1() throws DiffException {
final Patch<String> patch = DiffUtils.diff(Arrays.asList("A","B","C","A","B","B","A"), Arrays.asList("C","B","A","B","A","C"));
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());

View File

@@ -1,7 +1,5 @@
package com.github.difflib;
import com.github.difflib.DiffUtils;
import com.github.difflib.UnifiedDiffUtils;
import com.github.difflib.algorithm.DiffException;
import com.github.difflib.patch.Patch;
import com.github.difflib.patch.PatchFailedException;
@@ -12,13 +10,14 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static java.util.stream.Collectors.joining;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
public class GenerateUnifiedDiffTest {
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))) {
@@ -112,11 +111,13 @@ public class GenerateUnifiedDiffTest {
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 = (List<String>) fromUnifiedPatch.applyTo(origLines);
assertTrue(revLines.size() == patchedLines.size());
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);

View File

@@ -7,9 +7,10 @@ package com.github.difflib;
*
*/
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/";

View File

@@ -15,18 +15,14 @@
*/
package com.github.difflib.algorithm.myers;
import com.github.difflib.algorithm.myers.MyersDiff;
import com.github.difflib.DiffUtils;
import com.github.difflib.algorithm.DiffAlgorithmListener;
import com.github.difflib.algorithm.DiffException;
import com.github.difflib.patch.Patch;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
@@ -38,10 +34,40 @@ public class MyersDiffTest {
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));
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() 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");
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());
}
}

View File

@@ -3,7 +3,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;
@@ -22,7 +22,7 @@ public class ComputeDifference {
// 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);
}
}

View File

@@ -1,7 +1,5 @@
package com.github.difflib.patch;
import com.github.difflib.patch.Patch;
import com.github.difflib.patch.PatchFailedException;
import com.github.difflib.DiffUtils;
import com.github.difflib.algorithm.DiffException;
import java.util.Arrays;

View File

@@ -1,10 +1,14 @@
package com.github.difflib.text;
import com.github.difflib.text.DiffRow;
import com.github.difflib.text.DiffRowGenerator;
import com.github.difflib.algorithm.DiffException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -25,6 +29,30 @@ public class DiffRowGeneratorTest {
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() 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";
@@ -69,14 +97,14 @@ public class DiffRowGeneratorTest {
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)
.columnWidth(5)
.build();
List<DiffRow> rows = generator.generateDiffRows(split(first), split(second));
print(rows);
@@ -86,7 +114,7 @@ public class DiffRowGeneratorTest {
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";
@@ -104,20 +132,20 @@ public class DiffRowGeneratorTest {
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"));
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";
@@ -131,14 +159,14 @@ public class DiffRowGeneratorTest {
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\">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() throws DiffException {
DiffRowGenerator generator = DiffRowGenerator.create()
@@ -146,51 +174,51 @@ public class DiffRowGeneratorTest {
.mergeOriginalRevised(true)
.inlineDiffByWord(true)
.build();
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("Test"),Arrays.asList("ester"));
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"));
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");
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");
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,");
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()
@@ -203,13 +231,13 @@ public class DiffRowGeneratorTest {
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());
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()
@@ -221,15 +249,172 @@ public class DiffRowGeneratorTest {
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());
}
@Test
public void testGeneratorIssue15() throws DiffException, 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() throws DiffException {
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() throws DiffException {
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() throws DiffException {
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() throws DiffException {
DiffRowGenerator generator = DiffRowGenerator.create()
.build();
List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("<"), Arrays.asList("<"));
assertEquals("[[EQUAL,&lt;,&lt;]]", rows.toString());
}
@Test
public void testGeneratorIssue41UserNormalizer() throws DiffException {
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() throws DiffException {
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());
}
}

View File

@@ -15,10 +15,8 @@
*/
package com.github.difflib.text;
import com.github.difflib.text.StringUtils;
import java.util.Collections;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
@@ -39,15 +37,7 @@ public class StringUtilsTest {
*/
@Test
public void testNormalize_String() {
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")));
assertEquals(" test", StringUtils.normalize("\ttest"));
}
/**
@@ -59,10 +49,10 @@ public class StringUtilsTest {
assertEquals("tes<br/>t", StringUtils.wrapText("test", 3));
assertEquals("test", StringUtils.wrapText("test", 10));
}
@Test(expected = IllegalArgumentException.class)
public void testWrapText_String_int_zero() {
assertEquals("test", StringUtils.wrapText("test", 0));
assertEquals("test", StringUtils.wrapText("test", -1));
}
}

View File

@@ -0,0 +1,144 @@
/*
* 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.Java6Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.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\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\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();
}
}

View File

@@ -0,0 +1,167 @@
package com.github.difflib.unifieddiff;
import com.github.difflib.DiffUtils;
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.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 java.util.stream.Collectors.joining;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Ignore;
import org.junit.Test;
public class UnifiedDiffRoundTripTest {
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 DiffException, 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 DiffException, 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() throws DiffException, IOException {
List<String> test = Arrays.asList("abc");
Patch<String> patch = DiffUtils.diff(test, test);
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");
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) {
fail(e.getMessage());
}
}
/**
* Issue 12
*/
@Test
@Ignore
public void testPatchWithNoDeltas() throws DiffException, 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 {
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() throws DiffException, IOException {
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);
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, IOException {
Patch<String> patch = DiffUtils.diff(origLines, revLines);
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 {
// 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);
if (!l1.equals(l2)) {
fail("Line " + (i + 1) + " of the patched file did not match the revised original");
}
}
} catch (PatchFailedException e) {
fail(e.getMessage());
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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 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 org.junit.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, writer);
// System.out.println(writer.toString());
}
static String readFile(URI path, Charset encoding)
throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}

View File

@@ -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

View File

@@ -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!");
}

View File

@@ -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
+
+

View File

@@ -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

View File

@@ -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

View 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,

View 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,

View File

@@ -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.
-->
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.
-->
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>
<netbeans.hint.jdkPlatform>JDK_1.8</netbeans.hint.jdkPlatform>
</properties>
</project-shared-configuration>

11
nbactions.xml Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action>
<actionName>CUSTOM-clean deploy</actionName>
<displayName>clean deploy</displayName>
<goals>
<goal>clean</goal>
<goal>deploy</goal>
</goals>
</action>
</actions>

230
pom.xml
View File

@@ -1,32 +1,39 @@
<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">
<?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>com.github.java-diff-utils</groupId>
<artifactId>diffutils</artifactId>
<packaging>jar</packaging>
<version>2.0</version>
<name>java-diff-utils</name>
<groupId>io.github.java-diff-utils</groupId>
<artifactId>java-diff-utils-parent</artifactId>
<version>4.4</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/wumpz/java-diff-utils</url>
<url>https://github.com/java-diff-utils/java-diff-utils</url>
<inceptionYear>2009</inceptionYear>
<!--
to make a local release
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>9</version>
</parent>
-->
<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.0</tag>
</scm>
<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/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.4</tag>
</scm>
<issueManagement>
<system>GitHub Issues</system>
<url>https://github.com/wumpz/java-diff-utils/issues</url>
<url>https://github.com/java-diff-utils/java-diff-utils/issues</url>
</issueManagement>
<organization>
@@ -38,14 +45,6 @@
<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>
@@ -56,77 +55,21 @@
<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>
<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>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</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>
<localCheckout>true</localCheckout>
<pushChanges>false</pushChanges>
<mavenExecutorId>forked-path</mavenExecutorId>
</configuration>
</plugin>
<plugin>
@@ -159,30 +102,102 @@
</execution>
</executions>
</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" />
<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" />
<module name="WhitespaceAfter" />
<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>8.18</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<version>2.22.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>
<goals>install</goals>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>sign-release-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<keyname>f22e0543</keyname>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>doclint-java8-disable</id>
<activation>
@@ -209,5 +224,4 @@
</build>
</profile>
</profiles>
</project>
</project>

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -1,41 +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.algorithm.DiffException;
/**
* 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);
}
}

View File

@@ -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() + "]";
}
}

View File

@@ -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() + "]";
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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() + "]";
}
}

View File

@@ -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);
}
}