mirror of
https://github.com/java-diff-utils/java-diff-utils.git
synced 2026-03-13 10:11:17 +08:00
Compare commits
67 Commits
java-diff-
...
java-diff-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71981d8faa | ||
|
|
af9d84cd71 | ||
|
|
1d8148ac05 | ||
|
|
0307c80edb | ||
|
|
5245ee8b77 | ||
|
|
b7c1aaeb2e | ||
|
|
1560c22034 | ||
|
|
1fdcf13803 | ||
|
|
509d5071fd | ||
|
|
94aafa7e68 | ||
|
|
23c80bc30d | ||
|
|
52e61d653f | ||
|
|
dad43159a8 | ||
|
|
0f7c32b983 | ||
|
|
ace11bc484 | ||
|
|
74586e6763 | ||
|
|
f955268003 | ||
|
|
aff6bfed29 | ||
|
|
5cc2cf4021 | ||
|
|
903982517a | ||
|
|
ba60ae8ca4 | ||
|
|
6279142d0a | ||
|
|
50da99fed0 | ||
|
|
54324fb792 | ||
|
|
8df690fdd2 | ||
|
|
281c073c56 | ||
|
|
1664490a9f | ||
|
|
02532a9720 | ||
|
|
9f88cf91fb | ||
|
|
dc5ecb8ded | ||
|
|
4cad0ea2b9 | ||
|
|
5aed9f2d9a | ||
|
|
2224a15ecf | ||
|
|
7d0fd54f66 | ||
|
|
15934d5b75 | ||
|
|
5aac378e9f | ||
|
|
912be299da | ||
|
|
a1f170eaa0 | ||
|
|
0fd3bd8e06 | ||
|
|
eeb819cad4 | ||
|
|
e73742c4fc | ||
|
|
0545519fc3 | ||
|
|
bc65f9703c | ||
|
|
ea9942da12 | ||
|
|
8fdd239961 | ||
|
|
37f9eafaa9 | ||
|
|
0fd38db8ae | ||
|
|
3663cb5d87 | ||
|
|
8ae1f6cbbf | ||
|
|
ab1e38c57b | ||
|
|
286e807232 | ||
|
|
c85296b63d | ||
|
|
4c457b39dc | ||
|
|
7dea4e2298 | ||
|
|
2b02951e89 | ||
|
|
894b8ba300 | ||
|
|
2294c5be7b | ||
|
|
7203d4890f | ||
|
|
e413d79ecd | ||
|
|
c765616957 | ||
|
|
24c3df1f39 | ||
|
|
9765052226 | ||
|
|
8bb4a9a8b1 | ||
|
|
89ce301123 | ||
|
|
3d5343c283 | ||
|
|
d384ab6178 | ||
|
|
f03df6cf38 |
8
.github/release.yml
vendored
Normal file
8
.github/release.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
changelog:
|
||||
categories:
|
||||
- title: Bugs solved
|
||||
labels:
|
||||
- "bug"
|
||||
- title: Changes and new Features
|
||||
labels:
|
||||
- "*"
|
||||
11
.github/workflows/maven.yml
vendored
11
.github/workflows/maven.yml
vendored
@@ -14,13 +14,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
java: [8, 11]
|
||||
java: [8, 11, 17]
|
||||
name: Java ${{ matrix.java }} building ...
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Java ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'zulu'
|
||||
java-version: ${{ matrix.java }}
|
||||
cache: 'maven'
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -5,10 +5,22 @@ 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]
|
||||
## [4.13]
|
||||
|
||||
* API change: due to Issue #159: the author of the algorithm is Eugene Myers, therefore classes and methods were renamed accordingly
|
||||
|
||||
### Changed
|
||||
|
||||
## [4.11]
|
||||
|
||||
### Changed
|
||||
|
||||
* bugfixing new UnifiedDiff reader
|
||||
* header for each file
|
||||
* skip empty lines
|
||||
* introduction of Meyers Diff Algorithm with Linear Space improvment (until matured this will not be the default diff algorithm)
|
||||
* introduction of DiffAlgorithmFactory to set the default diff algorithm DiffUtils use (`DiffUtils.withDefaultDiffAlgorithmFactory(MeyersDiffWithLinearSpace.factory());`)
|
||||
|
||||
## [4.10]
|
||||
|
||||
### Changed
|
||||
|
||||
45
README.md
45
README.md
@@ -20,7 +20,7 @@ Main reason to build this library was the lack of easy-to-use libraries with all
|
||||
|
||||
## API
|
||||
|
||||
Javadocs of the actual release version: [JavaDocs java-diff-utils](https://java-diff-utils.github.io/java-diff-utils/4.7/docs/api/)
|
||||
Javadocs of the actual release version: [JavaDocs java-diff-utils](https://java-diff-utils.github.io/java-diff-utils/4.10/docs/apidocs/)
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -30,10 +30,46 @@ These two outputs are generated using this java-diff-utils. The source code can
|
||||
|
||||
**Producing a one liner including all difference information.**
|
||||
|
||||
```Java
|
||||
//create a configured DiffRowGenerator
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~") //introduce markdown style for strikethrough
|
||||
.newTag(f -> "**") //introduce markdown style for bold
|
||||
.build();
|
||||
|
||||
//compute the differences for two test texts.
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test senctence."),
|
||||
Arrays.asList("This is a test for diffutils."));
|
||||
|
||||
System.out.println(rows.get(0).getOldLine());
|
||||
```
|
||||
|
||||
This is a test ~senctence~**for diffutils**.
|
||||
|
||||
**Producing a side by side view of computed differences.**
|
||||
|
||||
```Java
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.inlineDiffByWord(true)
|
||||
.oldTag(f -> "~")
|
||||
.newTag(f -> "**")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList("This is a test senctence.", "This is the second line.", "And here is the finish."),
|
||||
Arrays.asList("This is a test for diffutils.", "This is the second line."));
|
||||
|
||||
System.out.println("|original|new|");
|
||||
System.out.println("|--------|---|");
|
||||
for (DiffRow row : rows) {
|
||||
System.out.println("|" + row.getOldLine() + "|" + row.getNewLine() + "|");
|
||||
}
|
||||
```
|
||||
|
||||
|original|new|
|
||||
|--------|---|
|
||||
|This is a test ~senctence~.|This is a test **for diffutils**.|
|
||||
@@ -49,7 +85,8 @@ This is a test ~senctence~**for diffutils**.
|
||||
* producing human-readable differences
|
||||
* inline difference construction
|
||||
* Algorithms:
|
||||
* Myer
|
||||
* Myers Standard Algorithm
|
||||
* Myers with linear space improvement
|
||||
* HistogramDiff using JGit Library
|
||||
|
||||
### Algorithms
|
||||
@@ -88,7 +125,7 @@ Just add the code below to your maven dependencies:
|
||||
<dependency>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -96,5 +133,5 @@ or using gradle:
|
||||
|
||||
```groovy
|
||||
// https://mvnrepository.com/artifact/io.github.java-diff-utils/java-diff-utils
|
||||
implementation "io.github.java-diff-utils:java-diff-utils:4.5"
|
||||
implementation "io.github.java-diff-utils:java-diff-utils:4.12"
|
||||
```
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.15</version>
|
||||
</parent>
|
||||
<artifactId>java-diff-utils-jgit</artifactId>
|
||||
<name>java-diff-utils-jgit</name>
|
||||
@@ -20,7 +20,7 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>5.8.1.202007141445-r</version>
|
||||
<version>5.13.3.202401111512-r</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.googlecode.javaewah</groupId>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.15</version>
|
||||
</parent>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.github.difflib;
|
||||
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.algorithm.myers.MyersDiff;
|
||||
@@ -29,84 +30,118 @@ import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* Implements the difference and patching engine
|
||||
* Utility class to implement the difference and patching engine.
|
||||
*/
|
||||
public final class DiffUtils {
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
*
|
||||
* @param <T> types to be diffed
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param progress progress listener
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
* This factory generates the DEFAULT_DIFF algorithm for all these routines.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), progress);
|
||||
}
|
||||
static DiffAlgorithmFactory DEFAULT_DIFF = MyersDiff.factory();
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), null);
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), null, includeEqualParts);
|
||||
/**
|
||||
* Sets the default diff algorithm factory to be used by all diff routines.
|
||||
*
|
||||
* @param factory a {@link DiffAlgorithmFactory} represnting the new default diff algorithm factory.
|
||||
*/
|
||||
public static void withDefaultDiffAlgorithmFactory(DiffAlgorithmFactory factory) {
|
||||
DEFAULT_DIFF = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised text.
|
||||
* Computes the difference between two sequences of elements using the default diff algorithm.
|
||||
*
|
||||
* @param <T> a generic representing the type of the elements to be compared.
|
||||
* @param original a {@link List} represnting the original sequence of elements. Must not be {@code null}.
|
||||
* @param revised a {@link List} represnting the revised sequence of elements. Must not be {@code null}.
|
||||
* @param progress a {@link DiffAlgorithmListener} represnting the progress listener. Can 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, DiffAlgorithmListener progress) {
|
||||
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between two sequences of elements using the default diff algorithm.
|
||||
*
|
||||
* @param <T> a generic representing the type of the elements to be compared.
|
||||
* @param original a {@link List} represnting the original sequence of elements. Must not be {@code null}.
|
||||
* @param revised a {@link List} represnting the revised sequence of elements. 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) {
|
||||
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between two sequences of elements using the default diff algorithm.
|
||||
*
|
||||
* @param <T> a generic representing the type of the elements to be compared.
|
||||
* @param original a {@link List} represnting the original sequence of elements. Must not be {@code null}.
|
||||
* @param revised a {@link List} represnting the revised sequence of elements. Must not be {@code null}.
|
||||
* @param includeEqualParts a {@link boolean} represnting whether to include equal parts in the resulting patch.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) {
|
||||
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null, includeEqualParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between two strings using the default diff algorithm.
|
||||
*
|
||||
* @param sourceText a {@link String} represnting the original string. Must not be {@code null}.
|
||||
* @param targetText a {@link String} represnting the revised string. Must not be {@code null}.
|
||||
* @param progress a {@link DiffAlgorithmListener} represnting the progress listener. Can be {@code null}.
|
||||
* @return The patch describing the difference between the original and revised strings. Never {@code null}.
|
||||
*/
|
||||
public static Patch<String> diff(String sourceText, String targetText,
|
||||
DiffAlgorithmListener progress) {
|
||||
DiffAlgorithmListener progress) {
|
||||
return DiffUtils.diff(
|
||||
Arrays.asList(sourceText.split("\n")),
|
||||
Arrays.asList(targetText.split("\n")), progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
* Computes the difference between the original and revised list of elements
|
||||
* with default diff algorithm
|
||||
*
|
||||
* @param 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 source a {@link List} represnting the original text. Must not be {@code null}.
|
||||
* @param target a {@link List} represnting the revised text. Must not be {@code null}.
|
||||
* @param equalizer a {@link BiPredicate} represnting 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> source, List<T> target,
|
||||
BiPredicate<T, T> equalizer) {
|
||||
BiPredicate<T, T> equalizer) {
|
||||
if (equalizer != null) {
|
||||
return DiffUtils.diff(source, target,
|
||||
new MyersDiff<>(equalizer));
|
||||
DEFAULT_DIFF.create(equalizer));
|
||||
}
|
||||
return DiffUtils.diff(source, target, new MyersDiff<>());
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) {
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) {
|
||||
return diff(original, revised, algorithm, progress, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
* Computes the difference between the original and revised list of elements
|
||||
* with default diff algorithm
|
||||
*
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param algorithm The diff algorithm. Must not be {@code null}.
|
||||
* @param progress The diff algorithm listener.
|
||||
* @param original a {@link List} represnting the original text. Must not be {@code null}.
|
||||
* @param revised a {@link List} represnting the revised text. Must not be {@code null}.
|
||||
* @param algorithm a {@link DiffAlgorithmI} represnting the diff algorithm. Must not be {@code null}.
|
||||
* @param progress a {@link DiffAlgorithmListener} represnting the diff algorithm listener.
|
||||
* @param includeEqualParts Include equal data parts into the patch.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
* @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, DiffAlgorithmListener progress,
|
||||
boolean includeEqualParts) {
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress,
|
||||
boolean includeEqualParts) {
|
||||
Objects.requireNonNull(original, "original must not be null");
|
||||
Objects.requireNonNull(revised, "revised must not be null");
|
||||
Objects.requireNonNull(algorithm, "algorithm must not be null");
|
||||
@@ -114,28 +149,30 @@ public final class DiffUtils {
|
||||
return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress), includeEqualParts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 original a {@link List} represnting the original text. Must not be {@code null}.
|
||||
* @param revised a {@link List} represnting the revised text. Must not be {@code null}.
|
||||
* @param algorithm a {@link DiffAlgorithmI} represnting the diff algorithm. Must not be {@code null}.
|
||||
* @return The patch describing the difference between the original and
|
||||
* revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmI<T> algorithm) {
|
||||
return diff(original, revised, algorithm, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the given texts inline. This one uses the "trick" to make out
|
||||
* of texts lists of characters, like DiffRowGenerator does and merges those changes at the end
|
||||
* together again.
|
||||
* 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
|
||||
* @param original a {@link String} represnting the original text. Must not be {@code null}.
|
||||
* @param revised a {@link String} represnting the revised text. Must not be {@code null}.
|
||||
* @return The patch describing the difference between the original and
|
||||
* revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static Patch<String> diffInline(String original, String revised) {
|
||||
List<String> origList = new ArrayList<>();
|
||||
@@ -154,20 +191,13 @@ public final class DiffUtils {
|
||||
return patch;
|
||||
}
|
||||
|
||||
private static List<String> compressLines(List<String> lines, String delimiter) {
|
||||
if (lines.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(String.join(delimiter, lines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the original text with given patch
|
||||
* Applies the given patch to the original list and returns the revised list.
|
||||
*
|
||||
* @param original the original text
|
||||
* @param patch the given patch
|
||||
* @return the revised text
|
||||
* @throws PatchFailedException if can't apply patch
|
||||
* @param original a {@link List} represnting the original list.
|
||||
* @param patch a {@link List} represnting the patch to apply.
|
||||
* @return the revised list.
|
||||
* @throws PatchFailedException if the patch cannot be applied.
|
||||
*/
|
||||
public static <T> List<T> patch(List<T> original, Patch<T> patch)
|
||||
throws PatchFailedException {
|
||||
@@ -175,16 +205,24 @@ public final class DiffUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpatch the revised text for a given patch
|
||||
* Applies the given patch to the revised list and returns the original list.
|
||||
*
|
||||
* @param revised the revised text
|
||||
* @param patch the given patch
|
||||
* @return the original text
|
||||
* @param revised a {@link List} represnting the revised list.
|
||||
* @param patch a {@link Patch} represnting the patch to apply.
|
||||
* @return the original list.
|
||||
* @throws PatchFailedException if the patch cannot be applied.
|
||||
*/
|
||||
public static <T> List<T> unpatch(List<T> revised, Patch<T> patch) {
|
||||
return patch.restore(revised);
|
||||
}
|
||||
|
||||
private static List<String> compressLines(List<String> lines, String delimiter) {
|
||||
if (lines.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(String.join(delimiter, lines));
|
||||
}
|
||||
|
||||
private DiffUtils() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,15 @@ import com.github.difflib.patch.ChangeDelta;
|
||||
import com.github.difflib.patch.Chunk;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -129,7 +133,7 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
/**
|
||||
* generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format
|
||||
* text representing the Patch.
|
||||
* text representing the Patch. Author: Bill James (tankerbay@gmail.com).
|
||||
*
|
||||
* @param originalFileName - Filename of the original (unrevised file)
|
||||
* @param revisedFileName - Filename of the revised file
|
||||
@@ -137,7 +141,6 @@ public final class UnifiedDiffUtils {
|
||||
* @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 originalFileName,
|
||||
String revisedFileName, List<String> originalLines, Patch<String> patch,
|
||||
@@ -200,13 +203,12 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
/**
|
||||
* processDeltas takes a list of Deltas and outputs them together in a single block of
|
||||
* Unified-Diff-format text.
|
||||
* Unified-Diff-format text. Author: Bill James (tankerbay@gmail.com).
|
||||
*
|
||||
* @param origLines - the lines of the original file
|
||||
* @param deltas - the Deltas to be output as a single block
|
||||
* @param contextSize - the number of lines of context to place around block
|
||||
* @return
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static List<String> processDeltas(List<String> origLines,
|
||||
List<AbstractDelta<String>> deltas, int contextSize, boolean newFile) {
|
||||
@@ -297,11 +299,10 @@ public final class UnifiedDiffUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter. Author: Bill James (tankerbay@gmail.com).
|
||||
*
|
||||
* @param delta - the Delta to output
|
||||
* @return list of String lines of code.
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static List<String> getDeltaText(AbstractDelta<String> delta) {
|
||||
List<String> buffer = new ArrayList<>();
|
||||
@@ -316,4 +317,151 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
private UnifiedDiffUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the differences between two files and return to the original file and diff format
|
||||
*
|
||||
* (This method compares the original file with the comparison file to obtain a diff, and inserts the diff into the corresponding position of the original file.
|
||||
* You can see all the differences and unmodified places from the original file.
|
||||
* Also, this will be very easy and useful for making side-by-side comparison display applications,
|
||||
* for example, if you use diff2html (https://github.com/rtfpessoa/diff2html#usage)
|
||||
* Wait for tools to display your differences on html pages, you only need to insert the return value into your js code)
|
||||
*
|
||||
* @param original Original file content
|
||||
* @param revised revised file content
|
||||
*
|
||||
*/
|
||||
public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised) {
|
||||
return generateOriginalAndDiff(original, revised, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare the differences between two files and return to the original file and diff format
|
||||
*
|
||||
* (This method compares the original file with the comparison file to obtain a diff, and inserts the diff into the corresponding position of the original file.
|
||||
* You can see all the differences and unmodified places from the original file.
|
||||
* Also, this will be very easy and useful for making side-by-side comparison display applications,
|
||||
* for example, if you use diff2html (https://github.com/rtfpessoa/diff2html#usage)
|
||||
* Wait for tools to display your differences on html pages, you only need to insert the return value into your js code)
|
||||
*
|
||||
* @param original Original file content
|
||||
* @param revised revised file content
|
||||
* @param originalFileName Original file name
|
||||
* @param revisedFileName revised file name
|
||||
*/
|
||||
public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised, String originalFileName, String revisedFileName) {
|
||||
String originalFileNameTemp = originalFileName;
|
||||
String revisedFileNameTemp = originalFileName;
|
||||
if (originalFileNameTemp == null) {
|
||||
originalFileNameTemp = "original";
|
||||
}
|
||||
if (revisedFileNameTemp == null) {
|
||||
revisedFileNameTemp = "revised";
|
||||
}
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
List<String> unifiedDiff = generateUnifiedDiff(originalFileNameTemp, revisedFileNameTemp, original, patch, 0);
|
||||
if (unifiedDiff.isEmpty()) {
|
||||
unifiedDiff.add("--- " + originalFileNameTemp);
|
||||
unifiedDiff.add("+++ " + revisedFileNameTemp);
|
||||
unifiedDiff.add("@@ -0,0 +0,0 @@");
|
||||
} else if (unifiedDiff.size() >= 3 && !unifiedDiff.get(2).contains("@@ -1,")) {
|
||||
unifiedDiff.set(1, unifiedDiff.get(1));
|
||||
unifiedDiff.add(2, "@@ -0,0 +0,0 @@");
|
||||
}
|
||||
List<String> originalWithPrefix = original.stream().map(v -> " " + v).collect(Collectors.toList());
|
||||
return insertOrig(originalWithPrefix, unifiedDiff);
|
||||
}
|
||||
|
||||
//Insert the diff format to the original file
|
||||
private static List<String> insertOrig(List<String> original, List<String> unifiedDiff) {
|
||||
List<String> result = new ArrayList<>();
|
||||
List<List<String>> diffList = new ArrayList<>();
|
||||
List<String> diff = new ArrayList<>();
|
||||
for (int i = 0; i < unifiedDiff.size(); i++) {
|
||||
String u = unifiedDiff.get(i);
|
||||
if (u.startsWith("@@") && !"@@ -0,0 +0,0 @@".equals(u) && !u.contains("@@ -1,")) {
|
||||
List<String> twoList = new ArrayList<>();
|
||||
twoList.addAll(diff);
|
||||
diffList.add(twoList);
|
||||
diff.clear();
|
||||
diff.add(u);
|
||||
continue;
|
||||
}
|
||||
if (i == unifiedDiff.size() - 1) {
|
||||
diff.add(u);
|
||||
List<String> twoList = new ArrayList<>();
|
||||
twoList.addAll(diff);
|
||||
diffList.add(twoList);
|
||||
diff.clear();
|
||||
break;
|
||||
}
|
||||
diff.add(u);
|
||||
}
|
||||
insertOrig(diffList, result, original);
|
||||
return result;
|
||||
}
|
||||
|
||||
//Insert the diff format to the original file
|
||||
private static void insertOrig(List<List<String>> diffList, List<String> result, List<String> original) {
|
||||
for (int i = 0; i < diffList.size(); i++) {
|
||||
List<String> diff = diffList.get(i);
|
||||
List<String> nexDiff = i == diffList.size() - 1 ? null : diffList.get(i + 1);
|
||||
String simb = i == 0 ? diff.get(2) : diff.get(0);
|
||||
String nexSimb = nexDiff == null ? null : nexDiff.get(0);
|
||||
insert(result, diff);
|
||||
Map<String, Integer> map = getRowMap(simb);
|
||||
if (null != nexSimb) {
|
||||
Map<String, Integer> nexMap = getRowMap(nexSimb);
|
||||
int start = 0;
|
||||
if (map.get("orgRow") != 0) {
|
||||
start = map.get("orgRow") + map.get("orgDel") - 1;
|
||||
}
|
||||
int end = nexMap.get("revRow") - 2;
|
||||
insert(result, getOrigList(original, start, end));
|
||||
}
|
||||
int start = map.get("orgRow") + map.get("orgDel") - 1;
|
||||
start = start == -1 ? 0 : start;
|
||||
if (simb.contains("@@ -1,") && null == nexSimb && map.get("orgDel") != original.size()) {
|
||||
insert(result, getOrigList(original, start, original.size() - 1));
|
||||
} else if (null == nexSimb && (map.get("orgRow") + map.get("orgDel") - 1) < original.size()) {
|
||||
insert(result, getOrigList(original, start, original.size() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Insert the unchanged content in the source file into result
|
||||
private static void insert(List<String> result, List<String> noChangeContent) {
|
||||
for (String ins : noChangeContent) {
|
||||
result.add(ins);
|
||||
}
|
||||
}
|
||||
|
||||
//Parse the line containing @@ to get the modified line number to delete or add a few lines
|
||||
private static Map<String, Integer> getRowMap(String str) {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
if (str.startsWith("@@")) {
|
||||
String[] sp = str.split(" ");
|
||||
String org = sp[1];
|
||||
String[] orgSp = org.split(",");
|
||||
map.put("orgRow", Integer.valueOf(orgSp[0].substring(1)));
|
||||
map.put("orgDel", Integer.valueOf(orgSp[1]));
|
||||
String[] revSp = org.split(",");
|
||||
map.put("revRow", Integer.valueOf(revSp[0].substring(1)));
|
||||
map.put("revAdd", Integer.valueOf(revSp[1]));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
//Get the specified part of the line from the original file
|
||||
private static List<String> getOrigList(List<String> originalWithPrefix, int start, int end) {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (originalWithPrefix.size() >= 1 && start <= end && end < originalWithPrefix.size()) {
|
||||
int startTemp = start;
|
||||
for (; startTemp <= end; startTemp++) {
|
||||
list.add(originalWithPrefix.get(startTemp));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,12 @@ public class Change {
|
||||
this.startRevised = startRevised;
|
||||
this.endRevised = endRevised;
|
||||
}
|
||||
|
||||
public Change withEndOriginal(int endOriginal) {
|
||||
return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised);
|
||||
}
|
||||
|
||||
public Change withEndRevised(int endRevised) {
|
||||
return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2021 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.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* Tool to create new instances of a diff algorithm. This one is only needed at the moment to
|
||||
* set DiffUtils default diff algorithm.
|
||||
* @author tw
|
||||
*/
|
||||
public interface DiffAlgorithmFactory {
|
||||
<T> DiffAlgorithmI<T> create();
|
||||
|
||||
<T> DiffAlgorithmI<T> create(BiPredicate<T, T> equalizer);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
@@ -30,11 +31,10 @@ import java.util.function.BiPredicate;
|
||||
*/
|
||||
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;
|
||||
equalizer = Object::equals;
|
||||
}
|
||||
|
||||
public MyersDiff(final BiPredicate<T, T> equalizer) {
|
||||
@@ -64,8 +64,9 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -139,8 +140,8 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
* @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");
|
||||
@@ -177,4 +178,23 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create instances of this specific diff algorithm.
|
||||
*/
|
||||
public static DiffAlgorithmFactory factory() {
|
||||
return new DiffAlgorithmFactory() {
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create() {
|
||||
return new MyersDiff<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create(BiPredicate < T, T > equalizer) {
|
||||
return new MyersDiff<>(equalizer);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
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;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
|
||||
|
||||
private final BiPredicate<T, T> equalizer;
|
||||
|
||||
public MyersDiffWithLinearSpace() {
|
||||
equalizer = Object::equals;
|
||||
}
|
||||
|
||||
public MyersDiffWithLinearSpace(final BiPredicate<T, T> equalizer) {
|
||||
Objects.requireNonNull(equalizer, "equalizer must not be null");
|
||||
this.equalizer = equalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
DiffData data = new DiffData(source, target);
|
||||
|
||||
int maxIdx = source.size() + target.size();
|
||||
|
||||
buildScript(data, 0, source.size(), 0, target.size(), idx -> {
|
||||
if (progress != null) {
|
||||
progress.diffStep(idx, maxIdx);
|
||||
}
|
||||
});
|
||||
|
||||
if (progress != null) {
|
||||
progress.diffEnd();
|
||||
}
|
||||
return data.script;
|
||||
}
|
||||
|
||||
private void buildScript(DiffData data, int start1, int end1, int start2, int end2, Consumer<Integer> progress) {
|
||||
if (progress != null) {
|
||||
progress.accept((end1 - start1) / 2 + (end2 - start2) / 2);
|
||||
}
|
||||
final Snake middle = getMiddleSnake(data, start1, end1, start2, end2);
|
||||
if (middle == null
|
||||
|| middle.start == end1 && middle.diag == end1 - end2
|
||||
|| middle.end == start1 && middle.diag == start1 - start2) {
|
||||
int i = start1;
|
||||
int j = start2;
|
||||
while (i < end1 || j < end2) {
|
||||
if (i < end1 && j < end2 && equalizer.test(data.source.get(i), data.target.get(j))) {
|
||||
//script.append(new KeepCommand<>(left.charAt(i)));
|
||||
++i;
|
||||
++j;
|
||||
} else {
|
||||
//TODO: compress these commands.
|
||||
if (end1 - start1 > end2 - start2) {
|
||||
//script.append(new DeleteCommand<>(left.charAt(i)));
|
||||
if (data.script.isEmpty()
|
||||
|| data.script.get(data.script.size() - 1).endOriginal != i
|
||||
|| data.script.get(data.script.size() - 1).deltaType != DeltaType.DELETE) {
|
||||
data.script.add(new Change(DeltaType.DELETE, i, i + 1, j, j));
|
||||
} else {
|
||||
data.script.set(data.script.size() - 1, data.script.get(data.script.size() - 1).withEndOriginal(i + 1));
|
||||
}
|
||||
++i;
|
||||
} else {
|
||||
if (data.script.isEmpty()
|
||||
|| data.script.get(data.script.size() - 1).endRevised != j
|
||||
|| data.script.get(data.script.size() - 1).deltaType != DeltaType.INSERT) {
|
||||
data.script.add(new Change(DeltaType.INSERT, i, i, j, j + 1));
|
||||
} else {
|
||||
data.script.set(data.script.size() - 1, data.script.get(data.script.size() - 1).withEndRevised(j + 1));
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buildScript(data, start1, middle.start, start2, middle.start - middle.diag, progress);
|
||||
buildScript(data, middle.end, end1, middle.end - middle.diag, end2, progress);
|
||||
}
|
||||
}
|
||||
|
||||
private Snake getMiddleSnake(DiffData data, int start1, int end1, int start2, int end2) {
|
||||
final int m = end1 - start1;
|
||||
final int n = end2 - start2;
|
||||
if (m == 0 || n == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int delta = m - n;
|
||||
final int sum = n + m;
|
||||
final int offset = (sum % 2 == 0 ? sum : sum + 1) / 2;
|
||||
data.vDown[1 + offset] = start1;
|
||||
data.vUp[1 + offset] = end1 + 1;
|
||||
|
||||
for (int d = 0; d <= offset; ++d) {
|
||||
// Down
|
||||
for (int k = -d; k <= d; k += 2) {
|
||||
// First step
|
||||
|
||||
final int i = k + offset;
|
||||
if (k == -d || k != d && data.vDown[i - 1] < data.vDown[i + 1]) {
|
||||
data.vDown[i] = data.vDown[i + 1];
|
||||
} else {
|
||||
data.vDown[i] = data.vDown[i - 1] + 1;
|
||||
}
|
||||
|
||||
int x = data.vDown[i];
|
||||
int y = x - start1 + start2 - k;
|
||||
|
||||
while (x < end1 && y < end2 && equalizer.test(data.source.get(x), data.target.get(y))) {
|
||||
data.vDown[i] = ++x;
|
||||
++y;
|
||||
}
|
||||
// Second step
|
||||
if (delta % 2 != 0 && delta - d <= k && k <= delta + d) {
|
||||
if (data.vUp[i - delta] <= data.vDown[i]) {
|
||||
return buildSnake(data, data.vUp[i - delta], k + start1 - start2, end1, end2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Up
|
||||
for (int k = delta - d; k <= delta + d; k += 2) {
|
||||
// First step
|
||||
final int i = k + offset - delta;
|
||||
if (k == delta - d
|
||||
|| k != delta + d && data.vUp[i + 1] <= data.vUp[i - 1]) {
|
||||
data.vUp[i] = data.vUp[i + 1] - 1;
|
||||
} else {
|
||||
data.vUp[i] = data.vUp[i - 1];
|
||||
}
|
||||
|
||||
int x = data.vUp[i] - 1;
|
||||
int y = x - start1 + start2 - k;
|
||||
while (x >= start1 && y >= start2 && equalizer.test(data.source.get(x), data.target.get(y))) {
|
||||
data.vUp[i] = x--;
|
||||
y--;
|
||||
}
|
||||
// Second step
|
||||
if (delta % 2 == 0 && -d <= k && k <= d) {
|
||||
if (data.vUp[i] <= data.vDown[i + delta]) {
|
||||
return buildSnake(data, data.vUp[i], k + start1 - start2, end1, end2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// According to Myers, this cannot happen
|
||||
throw new IllegalStateException("could not find a diff path");
|
||||
}
|
||||
|
||||
private Snake buildSnake(DiffData data, final int start, final int diag, final int end1, final int end2) {
|
||||
int end = start;
|
||||
while (end - diag < end2 && end < end1 && equalizer.test(data.source.get(end), data.target.get(end - diag))) {
|
||||
++end;
|
||||
}
|
||||
return new Snake(start, end, diag);
|
||||
}
|
||||
|
||||
private class DiffData {
|
||||
|
||||
final int size;
|
||||
final int[] vDown;
|
||||
final int[] vUp;
|
||||
final List<Change> script;
|
||||
final List<T> source;
|
||||
final List<T> target;
|
||||
|
||||
public DiffData(List<T> source, List<T> target) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
size = source.size() + target.size() + 2;
|
||||
vDown = new int[size];
|
||||
vUp = new int[size];
|
||||
script = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private class Snake {
|
||||
|
||||
final int start;
|
||||
final int end;
|
||||
final int diag;
|
||||
|
||||
public Snake(final int start, final int end, final int diag) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.diag = diag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create instances of this specific diff algorithm.
|
||||
*/
|
||||
public static DiffAlgorithmFactory factory() {
|
||||
return new DiffAlgorithmFactory() {
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create() {
|
||||
return new MyersDiffWithLinearSpace<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create(BiPredicate < T, T > equalizer) {
|
||||
return new MyersDiffWithLinearSpace<>(equalizer);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractDelta<T> implements Serializable {
|
||||
return getSource().verifyChunk(target);
|
||||
}
|
||||
|
||||
protected VerifyChunk verifyAntApplyTo(List<T> target) throws PatchFailedException {
|
||||
protected VerifyChunk verifyAndApplyTo(List<T> target) throws PatchFailedException {
|
||||
final VerifyChunk verify = verifyChunkToFitTarget(target);
|
||||
if (verify == VerifyChunk.OK) {
|
||||
applyTo(target);
|
||||
@@ -70,6 +70,19 @@ public abstract class AbstractDelta<T> implements Serializable {
|
||||
|
||||
protected abstract void restore(List<T> target);
|
||||
|
||||
/**
|
||||
* Apply patch fuzzy.
|
||||
*
|
||||
* @param target the list this patch will be applied to
|
||||
* @param fuzz the number of elements to ignore before/after the patched elements
|
||||
* @param position the position this patch will be applied to. ignores {@code source.getPosition()}
|
||||
* @see <a href="https://www.gnu.org/software/diffutils/manual/html_node/Inexact.html">Description of Fuzzy Patch</a> for more information.
|
||||
*/
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException {
|
||||
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not supports applying patch fuzzy");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new delta of the actual instance with customized chunk data.
|
||||
*/
|
||||
|
||||
@@ -66,6 +66,19 @@ public final class ChangeDelta<T> extends AbstractDelta<T> {
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException {
|
||||
int size = getSource().size();
|
||||
for (int i = fuzz; i < size - fuzz; i++) {
|
||||
target.remove(position + fuzz);
|
||||
}
|
||||
|
||||
int i = fuzz;
|
||||
for (T line : getTarget().getLines().subList(fuzz, getTarget().size() - fuzz)) {
|
||||
target.add(position + i, line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
|
||||
@@ -95,10 +95,28 @@ public final class Chunk<T> implements Serializable {
|
||||
* @throws com.github.difflib.patch.PatchFailedException
|
||||
*/
|
||||
public VerifyChunk verifyChunk(List<T> target) throws PatchFailedException {
|
||||
if (position > target.size() || last() > target.size()) {
|
||||
return verifyChunk(target, 0, getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that this chunk's saved text matches the corresponding text in
|
||||
* the given sequence.
|
||||
*
|
||||
* @param target the sequence to verify against.
|
||||
* @param fuzz the count of ignored prefix/suffix
|
||||
* @param position the position of target
|
||||
* @throws com.github.difflib.patch.PatchFailedException
|
||||
*/
|
||||
public VerifyChunk verifyChunk(List<T> target, int fuzz, int position) throws PatchFailedException {
|
||||
//noinspection UnnecessaryLocalVariable
|
||||
int startIndex = fuzz;
|
||||
int lastIndex = size() - fuzz;
|
||||
int last = position + size() - 1;
|
||||
|
||||
if (position + fuzz > target.size() || last - fuzz > target.size()) {
|
||||
return VerifyChunk.POSITION_OUT_OF_TARGET;
|
||||
}
|
||||
for (int i = 0; i < size(); i++) {
|
||||
for (int i = startIndex; i < lastIndex; i++) {
|
||||
if (!target.get(position + i).equals(lines.get(i))) {
|
||||
return VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ public class EqualDelta<T> extends AbstractDelta<T> {
|
||||
protected void restore(List<T> target) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void applyFuzzyToAt(List<T> target, int fuzz, int delta) {
|
||||
// equals so no operations
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[EqualDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
|
||||
@@ -48,22 +48,146 @@ public final class Patch<T> implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this patch to the given target
|
||||
* Creates a new list, the patch is being applied to.
|
||||
*
|
||||
* @return the patched text
|
||||
* @throws PatchFailedException if can't apply patch
|
||||
* @param target The list to apply the changes to.
|
||||
* @return A new list containing the applied patch.
|
||||
* @throws PatchFailedException if the patch cannot be applied
|
||||
*/
|
||||
public List<T> applyTo(List<T> target) throws PatchFailedException {
|
||||
List<T> result = new ArrayList<>(target);
|
||||
applyToExisting(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the patch to the supplied list.
|
||||
*
|
||||
* @param target The list to apply the changes to. This list has to be modifiable,
|
||||
* otherwise exceptions may be thrown, depending on the used type of list.
|
||||
* @throws PatchFailedException if the patch cannot be applied
|
||||
* @throws RuntimeException (or similar) if the list is not modifiable.
|
||||
*/
|
||||
public void applyToExisting(List<T> target) throws PatchFailedException {
|
||||
ListIterator<AbstractDelta<T>> it = getDeltas().listIterator(deltas.size());
|
||||
while (it.hasPrevious()) {
|
||||
AbstractDelta<T> delta = it.previous();
|
||||
VerifyChunk valid = delta.verifyAntApplyTo(result);
|
||||
VerifyChunk valid = delta.verifyAndApplyTo(target);
|
||||
if (valid != VerifyChunk.OK) {
|
||||
conflictOutput.processConflict(valid, delta, result);
|
||||
conflictOutput.processConflict(valid, delta, target);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class PatchApplyingContext<T> {
|
||||
public final List<T> result;
|
||||
public final int maxFuzz;
|
||||
|
||||
// the position last patch applied to.
|
||||
public int lastPatchEnd = -1;
|
||||
|
||||
///// passing values from find to apply
|
||||
public int currentFuzz = 0;
|
||||
|
||||
public int defaultPosition;
|
||||
public boolean beforeOutRange = false;
|
||||
public boolean afterOutRange = false;
|
||||
|
||||
private PatchApplyingContext(List<T> result, int maxFuzz) {
|
||||
this.result = result;
|
||||
this.maxFuzz = maxFuzz;
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> applyFuzzy(List<T> target, int maxFuzz) throws PatchFailedException {
|
||||
PatchApplyingContext<T> ctx = new PatchApplyingContext<>(new ArrayList<>(target), maxFuzz);
|
||||
|
||||
// the difference between patch's position and actually applied position
|
||||
int lastPatchDelta = 0;
|
||||
|
||||
for (AbstractDelta<T> delta : getDeltas()) {
|
||||
ctx.defaultPosition = delta.getSource().getPosition() + lastPatchDelta;
|
||||
int patchPosition = findPositionFuzzy(ctx, delta);
|
||||
if (0 <= patchPosition) {
|
||||
delta.applyFuzzyToAt(ctx.result, ctx.currentFuzz, patchPosition);
|
||||
lastPatchDelta = patchPosition - delta.getSource().getPosition();
|
||||
ctx.lastPatchEnd = delta.getSource().last() + lastPatchDelta;
|
||||
} else {
|
||||
conflictOutput.processConflict(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET, delta, ctx.result);
|
||||
}
|
||||
}
|
||||
|
||||
return ctx.result;
|
||||
}
|
||||
|
||||
// negative for not found
|
||||
private int findPositionFuzzy(PatchApplyingContext<T> ctx, AbstractDelta<T> delta) throws PatchFailedException {
|
||||
for (int fuzz = 0; fuzz <= ctx.maxFuzz; fuzz++) {
|
||||
ctx.currentFuzz = fuzz;
|
||||
int foundPosition = findPositionWithFuzz(ctx, delta, fuzz);
|
||||
if (foundPosition >= 0) {
|
||||
return foundPosition;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// negative for not found
|
||||
private int findPositionWithFuzz(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz) throws PatchFailedException {
|
||||
if (delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition) == VerifyChunk.OK) {
|
||||
return ctx.defaultPosition;
|
||||
}
|
||||
|
||||
ctx.beforeOutRange = false;
|
||||
ctx.afterOutRange = false;
|
||||
|
||||
// moreDelta >= 0: just for overflow guard, not a normal condition
|
||||
//noinspection OverflowingLoopIndex
|
||||
for (int moreDelta = 0; moreDelta >= 0; moreDelta++) {
|
||||
int pos = findPositionWithFuzzAndMoreDelta(ctx, delta, fuzz, moreDelta);
|
||||
if (pos >= 0) {
|
||||
return pos;
|
||||
}
|
||||
if (ctx.beforeOutRange && ctx.afterOutRange) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// negative for not found
|
||||
private int findPositionWithFuzzAndMoreDelta(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz, int moreDelta) throws PatchFailedException {
|
||||
// range check: can't apply before end of last patch
|
||||
if (!ctx.beforeOutRange) {
|
||||
int beginAt = ctx.defaultPosition - moreDelta + fuzz;
|
||||
// We can't apply patch before end of last patch.
|
||||
if (beginAt <= ctx.lastPatchEnd) {
|
||||
ctx.beforeOutRange = true;
|
||||
}
|
||||
}
|
||||
// range check: can't apply after end of result
|
||||
if (!ctx.afterOutRange) {
|
||||
int beginAt = ctx.defaultPosition + moreDelta + delta.getSource().size() - fuzz;
|
||||
// We can't apply patch before end of last patch.
|
||||
if (ctx.result.size() < beginAt) {
|
||||
ctx.afterOutRange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx.beforeOutRange) {
|
||||
VerifyChunk before = delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition - moreDelta);
|
||||
if (before == VerifyChunk.OK) {
|
||||
return ctx.defaultPosition - moreDelta;
|
||||
}
|
||||
}
|
||||
if (!ctx.afterOutRange) {
|
||||
VerifyChunk after = delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition + moreDelta);
|
||||
if (after == VerifyChunk.OK) {
|
||||
return ctx.defaultPosition + moreDelta;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,19 +233,33 @@ public final class Patch<T> implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the text to original. Opposite to applyTo() method.
|
||||
* Creates a new list, containing the restored state of the given list.
|
||||
* Opposite to {@link #applyTo(List)} method.
|
||||
*
|
||||
* @param target the given target
|
||||
* @return the restored text
|
||||
* @param target The list to copy and apply changes to.
|
||||
* @return A new list, containing the restored state.
|
||||
*/
|
||||
public List<T> restore(List<T> target) {
|
||||
List<T> result = new ArrayList<>(target);
|
||||
restoreToExisting(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restores all changes within the given list.
|
||||
* Opposite to {@link #applyToExisting(List)} method.
|
||||
*
|
||||
* @param target The list to restore changes in. This list has to be modifiable,
|
||||
* otherwise exceptions may be thrown, depending on the used type of list.
|
||||
* @throws RuntimeException (or similar) if the list is not modifiable.
|
||||
*/
|
||||
public void restoreToExisting(List<T> target) {
|
||||
ListIterator<AbstractDelta<T>> it = getDeltas().listIterator(deltas.size());
|
||||
while (it.hasPrevious()) {
|
||||
AbstractDelta<T> delta = it.previous();
|
||||
delta.restore(result);
|
||||
delta.restore(target);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,7 @@ public final class DiffRowGenerator {
|
||||
return list;
|
||||
};
|
||||
|
||||
public static final Pattern SPLIT_BY_WORD_PATTERN = Pattern.compile("\\s+|[,.\\[\\](){}/\\\\*+\\-#]");
|
||||
public static final Pattern SPLIT_BY_WORD_PATTERN = Pattern.compile("\\s+|[,.\\[\\](){}/\\\\*+\\-#<>;:&\\']+");
|
||||
|
||||
/**
|
||||
* Splitting lines by word to achieve word by word diff checking.
|
||||
@@ -173,6 +173,7 @@ public final class DiffRowGenerator {
|
||||
|
||||
private final boolean showInlineDiffs;
|
||||
private final boolean replaceOriginalLinefeedInChangesWithSpaces;
|
||||
private final boolean decompressDeltas;
|
||||
|
||||
private DiffRowGenerator(Builder builder) {
|
||||
showInlineDiffs = builder.showInlineDiffs;
|
||||
@@ -182,6 +183,7 @@ public final class DiffRowGenerator {
|
||||
columnWidth = builder.columnWidth;
|
||||
mergeOriginalRevised = builder.mergeOriginalRevised;
|
||||
inlineDiffSplitter = builder.inlineDiffSplitter;
|
||||
decompressDeltas = builder.decompressDeltas;
|
||||
|
||||
if (builder.equalizer != null) {
|
||||
equalizer = builder.equalizer;
|
||||
@@ -225,8 +227,14 @@ public final class DiffRowGenerator {
|
||||
int endPos = 0;
|
||||
final List<AbstractDelta<String>> deltaList = patch.getDeltas();
|
||||
|
||||
for (AbstractDelta<String> originalDelta : deltaList) {
|
||||
for (AbstractDelta<String> delta : decompressDeltas(originalDelta)) {
|
||||
if (decompressDeltas) {
|
||||
for (AbstractDelta<String> originalDelta : deltaList) {
|
||||
for (AbstractDelta<String> delta : decompressDeltas(originalDelta)) {
|
||||
endPos = transformDeltaIntoDiffRow(original, endPos, diffRows, delta);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (AbstractDelta<String> delta : deltaList) {
|
||||
endPos = transformDeltaIntoDiffRow(original, endPos, diffRows, delta);
|
||||
}
|
||||
}
|
||||
@@ -442,6 +450,7 @@ public final class DiffRowGenerator {
|
||||
|
||||
private boolean showInlineDiffs = false;
|
||||
private boolean ignoreWhiteSpaces = false;
|
||||
private boolean decompressDeltas = true;
|
||||
|
||||
private BiFunction<Tag, Boolean, String> oldTag
|
||||
= (tag, f) -> f ? "<span class=\"editOldInline\">" : "</span>";
|
||||
@@ -483,11 +492,10 @@ public final class DiffRowGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the originial old and new text lines to Diffrow without any
|
||||
* additional processing and without any tags to highlight the change.
|
||||
* Report all lines without markup on the old or new text.
|
||||
*
|
||||
* @param val the value to set. Default: false.
|
||||
* @return builder with configured reportLinesUnWrapped parameter
|
||||
* @return builder with configured reportLinesUnchanged parameter
|
||||
*/
|
||||
public Builder reportLinesUnchanged(final boolean val) {
|
||||
reportLinesUnchanged = val;
|
||||
@@ -554,8 +562,9 @@ public final class DiffRowGenerator {
|
||||
* Set the column width of generated lines of original and revised
|
||||
* texts.
|
||||
*
|
||||
* @param width the width to set. Making it < 0 doesn't make any sense.
|
||||
* Default 80. @return builder with config of column width
|
||||
* @param width the width to set. Making it < 0 doesn't make any
|
||||
* sense. Default 80.
|
||||
* @return builder with config of column width
|
||||
*/
|
||||
public Builder columnWidth(int width) {
|
||||
if (width >= 0) {
|
||||
@@ -586,6 +595,19 @@ public final class DiffRowGenerator {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deltas could be in a state, that would produce some unreasonable
|
||||
* results within an inline diff. So the deltas are decompressed into
|
||||
* smaller parts and rebuild. But this could result in more differences.
|
||||
*
|
||||
* @param decompressDeltas
|
||||
* @return
|
||||
*/
|
||||
public Builder decompressDeltas(boolean decompressDeltas) {
|
||||
this.decompressDeltas = decompressDeltas;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per default each character is separatly processed. This variant
|
||||
* introduces processing by word, which does not deliver in word
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class UnifiedDiff {
|
||||
return tail;
|
||||
}
|
||||
|
||||
public List<String> spplyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException {
|
||||
public List<String> applyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException {
|
||||
UnifiedDiffFile file = files.stream()
|
||||
.filter(diff -> findFile.test(diff.getFromFile()))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
@@ -30,10 +30,17 @@ public final class UnifiedDiffFile {
|
||||
private String toFile;
|
||||
private String renameFrom;
|
||||
private String renameTo;
|
||||
private String copyFrom;
|
||||
private String copyTo;
|
||||
private String toTimestamp;
|
||||
private String index;
|
||||
private String newFileMode;
|
||||
private String oldMode;
|
||||
private String newMode;
|
||||
private String deletedFileMode;
|
||||
private String binaryAdded;
|
||||
private String binaryDeleted;
|
||||
private String binaryEdited;
|
||||
private Patch<String> patch = new Patch<>();
|
||||
private boolean noNewLineAtTheEndOfTheFile = false;
|
||||
private Integer similarityIndex;
|
||||
@@ -114,6 +121,22 @@ public final class UnifiedDiffFile {
|
||||
this.renameTo = renameTo;
|
||||
}
|
||||
|
||||
public String getCopyFrom() {
|
||||
return copyFrom;
|
||||
}
|
||||
|
||||
public void setCopyFrom(String copyFrom) {
|
||||
this.copyFrom = copyFrom;
|
||||
}
|
||||
|
||||
public String getCopyTo() {
|
||||
return copyTo;
|
||||
}
|
||||
|
||||
public void setCopyTo(String copyTo) {
|
||||
this.copyTo = copyTo;
|
||||
}
|
||||
|
||||
public static UnifiedDiffFile from(String fromFile, String toFile, Patch<String> patch) {
|
||||
UnifiedDiffFile file = new UnifiedDiffFile();
|
||||
file.setFromFile(fromFile);
|
||||
@@ -138,6 +161,46 @@ public final class UnifiedDiffFile {
|
||||
this.deletedFileMode = deletedFileMode;
|
||||
}
|
||||
|
||||
public String getOldMode() {
|
||||
return oldMode;
|
||||
}
|
||||
|
||||
public void setOldMode(String oldMode) {
|
||||
this.oldMode = oldMode;
|
||||
}
|
||||
|
||||
public String getNewMode() {
|
||||
return newMode;
|
||||
}
|
||||
|
||||
public void setNewMode(String newMode) {
|
||||
this.newMode = newMode;
|
||||
}
|
||||
|
||||
public String getBinaryAdded() {
|
||||
return binaryAdded;
|
||||
}
|
||||
|
||||
public void setBinaryAdded(String binaryAdded) {
|
||||
this.binaryAdded = binaryAdded;
|
||||
}
|
||||
|
||||
public String getBinaryDeleted() {
|
||||
return binaryDeleted;
|
||||
}
|
||||
|
||||
public void setBinaryDeleted(String binaryDeleted) {
|
||||
this.binaryDeleted = binaryDeleted;
|
||||
}
|
||||
|
||||
public String getBinaryEdited() {
|
||||
return binaryEdited;
|
||||
}
|
||||
|
||||
public void setBinaryEdited(String binaryEdited) {
|
||||
this.binaryEdited = binaryEdited;
|
||||
}
|
||||
|
||||
public boolean isNoNewLineAtTheEndOfTheFile() {
|
||||
return noNewLineAtTheEndOfTheFile;
|
||||
}
|
||||
|
||||
@@ -51,11 +51,18 @@ public final class UnifiedDiffReader {
|
||||
private final UnifiedDiffLine TO_FILE = new UnifiedDiffLine(true, "^\\+\\+\\+\\s", this::processToFile);
|
||||
private final UnifiedDiffLine RENAME_FROM = new UnifiedDiffLine(true, "^rename\\sfrom\\s(.+)$", this::processRenameFrom);
|
||||
private final UnifiedDiffLine RENAME_TO = new UnifiedDiffLine(true, "^rename\\sto\\s(.+)$", this::processRenameTo);
|
||||
|
||||
private final UnifiedDiffLine COPY_FROM = new UnifiedDiffLine(true, "^copy\\sfrom\\s(.+)$", this::processCopyFrom);
|
||||
private final UnifiedDiffLine COPY_TO = new UnifiedDiffLine(true, "^copy\\sto\\s(.+)$", this::processCopyTo);
|
||||
|
||||
private final UnifiedDiffLine NEW_FILE_MODE = new UnifiedDiffLine(true, "^new\\sfile\\smode\\s(\\d+)", this::processNewFileMode);
|
||||
|
||||
private final UnifiedDiffLine DELETED_FILE_MODE = new UnifiedDiffLine(true, "^deleted\\sfile\\smode\\s(\\d+)", this::processDeletedFileMode);
|
||||
|
||||
private final UnifiedDiffLine OLD_MODE = new UnifiedDiffLine(true, "^old\\smode\\s(\\d+)", this::processOldMode);
|
||||
private final UnifiedDiffLine NEW_MODE = new UnifiedDiffLine(true, "^new\\smode\\s(\\d+)", this::processNewMode);
|
||||
private final UnifiedDiffLine BINARY_ADDED = new UnifiedDiffLine(true, "^Binary\\sfiles\\s/dev/null\\sand\\sb/(.+)\\sdiffer", this::processBinaryAdded);
|
||||
private final UnifiedDiffLine BINARY_DELETED = new UnifiedDiffLine(true, "^Binary\\sfiles\\sa/(.+)\\sand\\s/dev/null\\sdiffer", this::processBinaryDeleted);
|
||||
private final UnifiedDiffLine BINARY_EDITED = new UnifiedDiffLine(true, "^Binary\\sfiles\\sa/(.+)\\sand\\sb/(.+)\\sdiffer", this::processBinaryEdited);
|
||||
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);
|
||||
@@ -72,32 +79,58 @@ public final class UnifiedDiffReader {
|
||||
// [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk],
|
||||
// [/^-/, del], [/^\+/, add], [/^\\ No newline at end of file$/, eof]];
|
||||
private UnifiedDiff parse() throws IOException, UnifiedDiffParserException {
|
||||
String headerTxt = "";
|
||||
LOG.log(Level.FINE, "header parsing");
|
||||
String line = null;
|
||||
while (READER.ready()) {
|
||||
line = READER.readLine();
|
||||
LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
if (DIFF_COMMAND.validLine(line) || INDEX.validLine(line)
|
||||
|| FROM_FILE.validLine(line) || TO_FILE.validLine(line)
|
||||
|| NEW_FILE_MODE.validLine(line)) {
|
||||
break;
|
||||
} else {
|
||||
headerTxt += line + "\n";
|
||||
}
|
||||
}
|
||||
if (!"".equals(headerTxt)) {
|
||||
data.setHeader(headerTxt);
|
||||
}
|
||||
// String headerTxt = "";
|
||||
// LOG.log(Level.FINE, "header parsing");
|
||||
// String line = null;
|
||||
// while (READER.ready()) {
|
||||
// line = READER.readLine();
|
||||
// LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
// if (DIFF_COMMAND.validLine(line) || INDEX.validLine(line)
|
||||
// || FROM_FILE.validLine(line) || TO_FILE.validLine(line)
|
||||
// || NEW_FILE_MODE.validLine(line)) {
|
||||
// break;
|
||||
// } else {
|
||||
// headerTxt += line + "\n";
|
||||
// }
|
||||
// }
|
||||
// if (!"".equals(headerTxt)) {
|
||||
// data.setHeader(headerTxt);
|
||||
// }
|
||||
|
||||
String line = READER.readLine();
|
||||
while (line != null) {
|
||||
if (!CHUNK.validLine(line)) {
|
||||
String headerTxt = "";
|
||||
LOG.log(Level.FINE, "header parsing");
|
||||
while (line != null) {
|
||||
LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
if (validLine(line, DIFF_COMMAND, SIMILARITY_INDEX, INDEX,
|
||||
FROM_FILE, TO_FILE,
|
||||
RENAME_FROM, RENAME_TO,
|
||||
COPY_FROM, COPY_TO,
|
||||
NEW_FILE_MODE, DELETED_FILE_MODE,
|
||||
OLD_MODE, NEW_MODE,
|
||||
BINARY_ADDED, BINARY_DELETED,
|
||||
BINARY_EDITED, CHUNK)) {
|
||||
break;
|
||||
} else {
|
||||
headerTxt += line + "\n";
|
||||
}
|
||||
line = READER.readLine();
|
||||
}
|
||||
if (!"".equals(headerTxt)) {
|
||||
data.setHeader(headerTxt);
|
||||
}
|
||||
if (line != null && !CHUNK.validLine(line)) {
|
||||
initFileIfNecessary();
|
||||
while (line != null && !CHUNK.validLine(line)) {
|
||||
if (!processLine(line, DIFF_COMMAND, SIMILARITY_INDEX, INDEX,
|
||||
FROM_FILE, TO_FILE,
|
||||
RENAME_FROM, RENAME_TO,
|
||||
NEW_FILE_MODE, DELETED_FILE_MODE)) {
|
||||
COPY_FROM, COPY_TO,
|
||||
NEW_FILE_MODE, DELETED_FILE_MODE,
|
||||
OLD_MODE, NEW_MODE,
|
||||
BINARY_ADDED , BINARY_DELETED,
|
||||
BINARY_EDITED)) {
|
||||
throw new UnifiedDiffParserException("expected file start line not found");
|
||||
}
|
||||
line = READER.readLine();
|
||||
@@ -106,6 +139,8 @@ public final class UnifiedDiffReader {
|
||||
if (line != null) {
|
||||
processLine(line, CHUNK);
|
||||
while ((line = READER.readLine()) != null) {
|
||||
line = checkForNoNewLineAtTheEndOfTheFile(line);
|
||||
|
||||
if (!processLine(line, LINE_NORMAL, LINE_ADD, LINE_DEL)) {
|
||||
throw new UnifiedDiffParserException("expected data line not found");
|
||||
}
|
||||
@@ -118,10 +153,7 @@ public final class UnifiedDiffReader {
|
||||
}
|
||||
line = READER.readLine();
|
||||
|
||||
if ("\\ No newline at end of file".equals(line)) {
|
||||
actualFile.setNoNewLineAtTheEndOfTheFile(true);
|
||||
line = READER.readLine();
|
||||
}
|
||||
line = checkForNoNewLineAtTheEndOfTheFile(line);
|
||||
}
|
||||
if (line == null || (line.startsWith("--") && !line.startsWith("---"))) {
|
||||
break;
|
||||
@@ -142,6 +174,14 @@ public final class UnifiedDiffReader {
|
||||
return data;
|
||||
}
|
||||
|
||||
private String checkForNoNewLineAtTheEndOfTheFile(String line) throws IOException {
|
||||
if ("\\ No newline at end of file".equals(line)) {
|
||||
actualFile.setNoNewLineAtTheEndOfTheFile(true);
|
||||
return READER.readLine();
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
static String[] parseFileNames(String line) {
|
||||
String[] split = line.split(" ");
|
||||
return new String[]{
|
||||
@@ -179,6 +219,19 @@ public final class UnifiedDiffReader {
|
||||
return false;
|
||||
//throw new UnifiedDiffParserException("parsing error at line " + line);
|
||||
}
|
||||
|
||||
private boolean validLine(String line, UnifiedDiffLine ... rules) {
|
||||
if (line == null) {
|
||||
return false;
|
||||
}
|
||||
for (UnifiedDiffLine rule : rules) {
|
||||
if (rule.validLine(line)) {
|
||||
LOG.fine(" >>> accepted rule " + rule.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initFileIfNecessary() {
|
||||
if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) {
|
||||
@@ -296,6 +349,14 @@ public final class UnifiedDiffReader {
|
||||
private void processRenameTo(MatchResult match, String line) {
|
||||
actualFile.setRenameTo(match.group(1));
|
||||
}
|
||||
|
||||
private void processCopyFrom(MatchResult match, String line) {
|
||||
actualFile.setCopyFrom(match.group(1));
|
||||
}
|
||||
|
||||
private void processCopyTo(MatchResult match, String line) {
|
||||
actualFile.setCopyTo(match.group(1));
|
||||
}
|
||||
|
||||
private void processNewFileMode(MatchResult match, String line) {
|
||||
//initFileIfNecessary();
|
||||
@@ -307,6 +368,26 @@ public final class UnifiedDiffReader {
|
||||
actualFile.setDeletedFileMode(match.group(1));
|
||||
}
|
||||
|
||||
private void processOldMode(MatchResult match, String line) {
|
||||
actualFile.setOldMode(match.group(1));
|
||||
}
|
||||
|
||||
private void processNewMode(MatchResult match, String line) {
|
||||
actualFile.setNewMode(match.group(1));
|
||||
}
|
||||
|
||||
private void processBinaryAdded(MatchResult match, String line) {
|
||||
actualFile.setBinaryAdded(match.group(1));
|
||||
}
|
||||
|
||||
private void processBinaryDeleted(MatchResult match, String line) {
|
||||
actualFile.setBinaryDeleted(match.group(1));
|
||||
}
|
||||
|
||||
private void processBinaryEdited(MatchResult match, String line) {
|
||||
actualFile.setBinaryEdited(match.group(1));
|
||||
}
|
||||
|
||||
private String extractFileName(String _line) {
|
||||
Matcher matcher = TIMESTAMP_REGEXP.matcher(_line);
|
||||
String line = _line;
|
||||
@@ -314,7 +395,7 @@ public final class UnifiedDiffReader {
|
||||
line = line.substring(0, matcher.start());
|
||||
}
|
||||
line = line.split("\t")[0];
|
||||
return line.substring(4).replaceFirst("^(a|b|old|new)(\\/)?", "")
|
||||
return line.substring(4).replaceFirst("^(a|b|old|new)/", "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
|
||||
@@ -189,10 +189,10 @@ public class UnifiedDiffWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter
|
||||
* 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.
|
||||
* @param writer consumer for the list of String lines of code
|
||||
* @param delta the Delta to output
|
||||
*/
|
||||
private static void getDeltaText(Consumer<String> writer, AbstractDelta<String> delta) {
|
||||
for (String line : delta.getSource().getLines()) {
|
||||
|
||||
@@ -13,6 +13,8 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -132,7 +134,7 @@ public class DiffUtilsTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* To test this, the greedy meyer algorithm is not suitable.
|
||||
* To test this, the greedy Myer algorithm is not suitable.
|
||||
*/
|
||||
@Test
|
||||
@Disabled
|
||||
@@ -227,4 +229,14 @@ public class DiffUtilsTest {
|
||||
assertEquals(new Chunk<>(3, Arrays.asList("brown")), delta.getSource());
|
||||
assertEquals(new Chunk<>(3, Arrays.asList("down")), delta.getTarget());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffPatchIssue189Problem() throws IOException {
|
||||
String original = new String(Files.readAllBytes(Paths.get("target/test-classes/com/github/difflib/text/issue_189_insert_original.txt")));
|
||||
String revised = new String(Files.readAllBytes(Paths.get("target/test-classes/com/github/difflib/text/issue_189_insert_revised.txt")));
|
||||
|
||||
Patch patch = DiffUtils.diff(Arrays.asList(original.split("\n")), Arrays.asList(revised.split("\n")));
|
||||
|
||||
assertEquals(1, patch.getDeltas().size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,5 +69,4 @@ public class MyersDiffTest {
|
||||
System.out.println(logdata);
|
||||
assertEquals(8, logdata.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import java.util.stream.IntStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class MyersDiffWithLinearSpaceTest {
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1Forward() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(original, revised, new MyersDiffWithLinearSpace<String>().computeDiff(original, revised, null));
|
||||
assertNotNull(patch);
|
||||
System.out.println(patch);
|
||||
assertEquals(5, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[InsertDelta, position: 0, lines: [C]], [DeleteDelta, position: 0, lines: [A]], [DeleteDelta, position: 2, lines: [C]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1ForwardWithListener() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
|
||||
List<String> logdata = new ArrayList<>();
|
||||
final Patch<String> patch = Patch.generate(original, revised,
|
||||
new MyersDiffWithLinearSpace<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);
|
||||
System.out.println(patch);
|
||||
assertEquals(5, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[InsertDelta, position: 0, lines: [C]], [DeleteDelta, position: 0, lines: [A]], [DeleteDelta, position: 2, lines: [C]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
System.out.println(logdata);
|
||||
assertEquals(11, logdata.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPerformanceProblemsIssue124() {
|
||||
List<String> old = Arrays.asList("abcd");
|
||||
List<String> newl = IntStream.range(0, 90000)
|
||||
.boxed()
|
||||
.map(i -> i.toString())
|
||||
.collect(toList());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
Patch<String> diff = DiffUtils.diff(old, newl, new MyersDiffWithLinearSpace<String>());
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Finished in " + (end - start) + "ms and resulted " + diff.getDeltas().size() + " deltas");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.patch.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
|
||||
public class WithMyersDiffWithLinearSpacePatchTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Insert() {
|
||||
final List<String> insertTest_from = Arrays.asList("hhh");
|
||||
final List<String> insertTest_to = Arrays.asList("hhh", "jjj", "kkk", "lll");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(insertTest_from, insertTest_to, new MyersDiffWithLinearSpace<String>());
|
||||
try {
|
||||
assertEquals(insertTest_to, DiffUtils.patch(insertTest_from, patch));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Delete() {
|
||||
final List<String> deleteTest_from = Arrays.asList("ddd", "fff", "ggg", "hhh");
|
||||
final List<String> deleteTest_to = Arrays.asList("ggg");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(deleteTest_from, deleteTest_to, new MyersDiffWithLinearSpace<String>());
|
||||
try {
|
||||
assertEquals(deleteTest_to, DiffUtils.patch(deleteTest_from, patch));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to, new MyersDiffWithLinearSpace<String>());
|
||||
try {
|
||||
assertEquals(changeTest_to, DiffUtils.patch(changeTest_from, patch));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// region testPatch_fuzzyApply utils
|
||||
|
||||
private List<String> intRange(int count) {
|
||||
return IntStream.range(0, count)
|
||||
.mapToObj(Integer::toString)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private final List<String> join(List<String>... lists) {
|
||||
return Arrays.stream(lists).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static class FuzzyApplyTestPair {
|
||||
public final List<String> from;
|
||||
public final List<String> to;
|
||||
public final int requiredFuzz;
|
||||
|
||||
private FuzzyApplyTestPair(List<String> from, List<String> to, int requiredFuzz) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.requiredFuzz = requiredFuzz;
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@Test
|
||||
public void fuzzyApply() throws PatchFailedException {
|
||||
Patch<String> patch = new Patch<>();
|
||||
List<String> deltaFrom = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff");
|
||||
List<String> deltaTo = Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff");
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(6, deltaFrom),
|
||||
new Chunk<>(6, deltaTo)));
|
||||
|
||||
//noinspection unchecked
|
||||
List<String>[] moves = new List[] {
|
||||
intRange(6), // no patch move
|
||||
intRange(3), // forward patch move
|
||||
intRange(9), // backward patch move
|
||||
intRange(0), // apply to the first
|
||||
};
|
||||
|
||||
for (FuzzyApplyTestPair pair : FUZZY_APPLY_TEST_PAIRS) {
|
||||
for (List<String> move : moves) {
|
||||
List<String> from = join(move, pair.from);
|
||||
List<String> to = join(move, pair.to);
|
||||
|
||||
for (int i = 0; i < pair.requiredFuzz; i++) {
|
||||
int maxFuzz = i;
|
||||
assertThrows(PatchFailedException.class, () ->
|
||||
patch.applyFuzzy(from, maxFuzz),
|
||||
() -> "fail for " + from + " -> " + to + " for fuzz " + maxFuzz + " required " + pair.requiredFuzz);
|
||||
}
|
||||
for (int i = pair.requiredFuzz; i < 4; i++) {
|
||||
int maxFuzz = i;
|
||||
assertEquals(to, patch.applyFuzzy(from, maxFuzz),
|
||||
() -> "with " + maxFuzz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fuzzyApplyTwoSideBySidePatches() throws PatchFailedException {
|
||||
Patch<String> patch = new Patch<>();
|
||||
List<String> deltaFrom = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff");
|
||||
List<String> deltaTo = Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff");
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(0, deltaFrom),
|
||||
new Chunk<>(0, deltaTo)));
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(6, deltaFrom),
|
||||
new Chunk<>(6, deltaTo)));
|
||||
|
||||
|
||||
assertEquals(join(deltaTo, deltaTo), patch.applyFuzzy(join(deltaFrom, deltaFrom), 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fuzzyApplyToNearest() throws PatchFailedException {
|
||||
Patch<String> patch = new Patch<>();
|
||||
List<String> deltaFrom = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff");
|
||||
List<String> deltaTo = Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff");
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(0, deltaFrom),
|
||||
new Chunk<>(0, deltaTo)));
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(10, deltaFrom),
|
||||
new Chunk<>(10, deltaTo)));
|
||||
|
||||
assertEquals(join(deltaTo, deltaFrom, deltaTo),
|
||||
patch.applyFuzzy(join(deltaFrom, deltaFrom, deltaFrom), 0));
|
||||
assertEquals(join(intRange(1), deltaTo, deltaFrom, deltaTo),
|
||||
patch.applyFuzzy(join(intRange(1), deltaFrom, deltaFrom, deltaFrom), 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Serializable() throws IOException, ClassNotFoundException {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to, new MyersDiffWithLinearSpace<String>());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(baos);
|
||||
out.writeObject(patch);
|
||||
out.close();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream in = new ObjectInputStream(bais);
|
||||
Patch<String> result = (Patch<String>) in.readObject();
|
||||
in.close();
|
||||
|
||||
try {
|
||||
assertEquals(changeTest_to, DiffUtils.patch(changeTest_from, result));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to, new MyersDiffWithLinearSpace<String>());
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(11, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "bxb", "cxc", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static class FuzzyApplyTestDataGenerator {
|
||||
private static String createList(List<String> values) {
|
||||
return values.stream()
|
||||
.map(x -> '"' + x + '"')
|
||||
.collect(Collectors.joining(", ", "Arrays.asList(", ")"));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String[] deltaFrom = new String[] { "aaa", "bbb", "ccc", "ddd", "eee", "fff" };
|
||||
String[] deltaTo = new String[] { "aaa", "bbb", "cxc", "dxd", "eee", "fff" };
|
||||
|
||||
List<FuzzyApplyTestPair> pairs = new ArrayList<>();
|
||||
|
||||
// create test data.
|
||||
// Brute-force search
|
||||
String[] changedValue = new String[]{"axa", "bxb", "czc", "dzd", "exe", "fxf"};
|
||||
for (int i = 0; i < 1 << 6; i++) {
|
||||
if ((i & 0b001100) != 0 && (i & 0b001100) != 0b001100) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] from = deltaFrom.clone();
|
||||
String[] to = deltaTo.clone();
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if ((i & (1 << j)) != 0) {
|
||||
from[j] = changedValue[j];
|
||||
to[j] = changedValue[j];
|
||||
}
|
||||
}
|
||||
|
||||
int requiredFuzz;
|
||||
if ((i & 0b001100) != 0) {
|
||||
requiredFuzz = 3;
|
||||
} else if ((i & 0b010010) != 0) {
|
||||
requiredFuzz = 2;
|
||||
} else if ((i & 0b100001) != 0) {
|
||||
requiredFuzz = 1;
|
||||
} else {
|
||||
requiredFuzz = 0;
|
||||
}
|
||||
|
||||
pairs.add(new FuzzyApplyTestPair(Arrays.asList(from), Arrays.asList(to), requiredFuzz));
|
||||
}
|
||||
pairs.sort(Comparator.comparingInt(a -> a.requiredFuzz));
|
||||
System.out.println("FuzzyApplyTestPair[] pairs = new FuzzyApplyTestPair[] {");
|
||||
for (FuzzyApplyTestPair pair : pairs) {
|
||||
System.out.println(" new FuzzyApplyTestPair(");
|
||||
System.out.println(" " + createList(pair.from) + ",");
|
||||
System.out.println(" " + createList(pair.to) + ",");
|
||||
System.out.println(" " + pair.requiredFuzz + "),");
|
||||
}
|
||||
System.out.println("};");
|
||||
}
|
||||
}
|
||||
|
||||
private static final FuzzyApplyTestPair[] FUZZY_APPLY_TEST_PAIRS = new FuzzyApplyTestPair[] {
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff"),
|
||||
0),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "eee", "fff"),
|
||||
1),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fxf"),
|
||||
1),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "eee", "fxf"),
|
||||
1),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "eee", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "eee", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "eee", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "eee", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
};
|
||||
}
|
||||
@@ -12,11 +12,11 @@ import java.util.List;
|
||||
public class ComputeDifference {
|
||||
|
||||
private static final String ORIGINAL = TestConstants.MOCK_FOLDER + "original.txt";
|
||||
private static final String RIVISED = TestConstants.MOCK_FOLDER + "revised.txt";
|
||||
private static final String REVISED = TestConstants.MOCK_FOLDER + "revised.txt";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
List<String> original = Files.readAllLines(new File(ORIGINAL).toPath());
|
||||
List<String> revised = Files.readAllLines(new File(RIVISED).toPath());
|
||||
List<String> revised = Files.readAllLines(new File(REVISED).toPath());
|
||||
|
||||
// Compute diff. Get the Patch object. Patch is the container for computed deltas.
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.github.difflib.examples;
|
||||
|
||||
import com.github.difflib.TestConstants;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class OriginalAndDiffTest {
|
||||
|
||||
@Test
|
||||
public void testGenerateOriginalAndDiff() {
|
||||
List<String> origLines = null;
|
||||
List<String> revLines = null;
|
||||
try {
|
||||
origLines = fileToLines(TestConstants.MOCK_FOLDER + "original.txt");
|
||||
revLines = fileToLines(TestConstants.MOCK_FOLDER + "revised.txt");
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
List<String> originalAndDiff = UnifiedDiffUtils.generateOriginalAndDiff(origLines, revLines);
|
||||
System.out.println(originalAndDiff.stream().collect(joining("\n")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateOriginalAndDiffFirstLineChange() {
|
||||
List<String> origLines = null;
|
||||
List<String> revLines = null;
|
||||
try {
|
||||
origLines = fileToLines(TestConstants.MOCK_FOLDER + "issue_170_original.txt");
|
||||
revLines = fileToLines(TestConstants.MOCK_FOLDER + "issue_170_revised.txt");
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
List<String> originalAndDiff = UnifiedDiffUtils.generateOriginalAndDiff(origLines, revLines);
|
||||
System.out.println(originalAndDiff.stream().collect(joining("\n")));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ChunkTest {
|
||||
@Test
|
||||
void verifyChunk() throws PatchFailedException {
|
||||
Chunk<Character> chunk = new Chunk<>(7, toCharList("test"));
|
||||
|
||||
// normal check
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix")));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix es suffix"), 0, 7));
|
||||
|
||||
// position
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("short test suffix"), 0, 6));
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("loonger test suffix"), 0, 8));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix"), 0, 6));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix"), 0, 8));
|
||||
|
||||
// fuzz
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix"), 1, 7));
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("prefix es suffix"), 1, 7));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix suffix"), 1, 7));
|
||||
}
|
||||
|
||||
private List<Character> toCharList(String str) {
|
||||
return str.chars().mapToObj(x -> (char) x).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -11,14 +11,34 @@ import java.io.ObjectOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.myers.MyersDiff;
|
||||
import com.github.difflib.algorithm.myers.MyersDiffWithLinearSpace;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class PatchTest {
|
||||
public class PatchWithAllDiffAlgorithmsTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Insert() {
|
||||
private static Stream<Arguments> provideAlgorithms() {
|
||||
return Stream.of(Arguments.of(MyersDiff.factory()),
|
||||
Arguments.of(MyersDiffWithLinearSpace.factory()));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAll() {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(MyersDiff.factory());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Insert(DiffAlgorithmFactory factory) {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> insertTest_from = Arrays.asList("hhh");
|
||||
final List<String> insertTest_to = Arrays.asList("hhh", "jjj", "kkk", "lll");
|
||||
|
||||
@@ -30,8 +50,11 @@ public class PatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Delete() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Delete(DiffAlgorithmFactory factory) {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> deleteTest_from = Arrays.asList("ddd", "fff", "ggg", "hhh");
|
||||
final List<String> deleteTest_to = Arrays.asList("ggg");
|
||||
|
||||
@@ -43,8 +66,11 @@ public class PatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Change(DiffAlgorithmFactory factory) {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
@@ -56,8 +82,11 @@ public class PatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Serializable() throws IOException, ClassNotFoundException {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Serializable(DiffAlgorithmFactory factory) throws IOException, ClassNotFoundException {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
@@ -77,27 +106,5 @@ public class PatchTest {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(9, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2021 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 com.github.difflib.DiffUtils;
|
||||
import static com.github.difflib.patch.Patch.CONFLICT_PRODUCES_MERGE_CONFLICT;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class PatchWithMyerDiffTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(9, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchThreeWayIssue138() throws PatchFailedException {
|
||||
List<String> base = Arrays.asList("Imagine there's no heaven".split("\\s+"));
|
||||
List<String> left = Arrays.asList("Imagine there's no HEAVEN".split("\\s+"));
|
||||
List<String> right = Arrays.asList("IMAGINE there's no heaven".split("\\s+"));
|
||||
|
||||
Patch<String> rightPatch = DiffUtils.diff(base, right)
|
||||
.withConflictOutput(CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
List<String> applied = rightPatch.applyTo(left);
|
||||
|
||||
assertEquals("IMAGINE there's no HEAVEN", applied.stream().collect(joining(" ")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2021 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 com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.myers.MyersDiff;
|
||||
import com.github.difflib.algorithm.myers.MyersDiffWithLinearSpace;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class PatchWithMyerDiffWithLinearSpaceTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setupClass() {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(MyersDiffWithLinearSpace.factory());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void resetClass() {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(MyersDiff.factory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(11, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "bxb", "cxc", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,12 @@
|
||||
package com.github.difflib.text;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.myers.MyersDiffWithLinearSpace;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
@@ -641,7 +646,7 @@ public class DiffRowGeneratorTest {
|
||||
|
||||
assertThat(rows).extracting(item -> item.getTag().name()).containsExactly("CHANGE", "DELETE", "EQUAL", "CHANGE", "EQUAL");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCorrectChangeIssue114_2() throws IOException {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "D", "E");
|
||||
@@ -662,7 +667,7 @@ public class DiffRowGeneratorTest {
|
||||
assertThat(rows).extracting(item -> item.getTag().name()).containsExactly("CHANGE", "DELETE", "EQUAL", "CHANGE", "EQUAL");
|
||||
assertThat(rows.get(1).toString()).isEqualTo("[DELETE,~B~,]");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIssue119WrongContextLength() throws IOException {
|
||||
String original = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue_119_original.txt")).collect(joining("\n"));
|
||||
@@ -683,4 +688,130 @@ public class DiffRowGeneratorTest {
|
||||
.filter(item -> item.getTag() != DiffRow.Tag.EQUAL)
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue129WithDeltaDecompression() {
|
||||
List<String> lines1 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein abc to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
List<String> lines2 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein",
|
||||
"xyz",
|
||||
"to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
int[] entry = {1};
|
||||
String txt = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.oldTag((tag, isOpening) -> isOpening ? "==old" + tag + "==>" : "<==old==")
|
||||
.newTag((tag, isOpening) -> isOpening ? "==new" + tag + "==>" : "<==new==")
|
||||
.build()
|
||||
.generateDiffRows(lines1, lines2)
|
||||
.stream()
|
||||
.map(row -> row.getTag().toString())
|
||||
.collect(joining(" "));
|
||||
// .forEachOrdered(row -> {
|
||||
// System.out.printf("%4d %-8s %-80s %-80s\n", entry[0]++,
|
||||
// row.getTag(), row.getOldLine(), row.getNewLine());
|
||||
// });
|
||||
|
||||
assertThat(txt).isEqualTo("EQUAL EQUAL EQUAL CHANGE INSERT INSERT EQUAL EQUAL EQUAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue129SkipDeltaDecompression() {
|
||||
List<String> lines1 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein abc to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
List<String> lines2 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein",
|
||||
"xyz",
|
||||
"to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
int[] entry = {1};
|
||||
String txt
|
||||
= DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.decompressDeltas(false)
|
||||
.oldTag((tag, isOpening) -> isOpening ? "==old" + tag + "==>" : "<==old==")
|
||||
.newTag((tag, isOpening) -> isOpening ? "==new" + tag + "==>" : "<==new==")
|
||||
.build()
|
||||
.generateDiffRows(lines1, lines2)
|
||||
.stream()
|
||||
.map(row -> row.getTag().toString())
|
||||
.collect(joining(" "));
|
||||
// .forEachOrdered(row -> {
|
||||
// System.out.printf("%4d %-8s %-80s %-80s\n", entry[0]++,
|
||||
// row.getTag(), row.getOldLine(), row.getNewLine());
|
||||
// });
|
||||
|
||||
assertThat(txt).isEqualTo("EQUAL EQUAL EQUAL CHANGE CHANGE CHANGE EQUAL EQUAL EQUAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue129SkipWhitespaceChanges() throws IOException {
|
||||
String original = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue129_1.txt")).collect(joining("\n"));
|
||||
String revised = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue129_2.txt")).collect(joining("\n"));
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.ignoreWhiteSpaces(true)
|
||||
.oldTag((tag, isOpening) -> isOpening ? "==old" + tag + "==>" : "<==old==")
|
||||
.newTag((tag, isOpening) -> isOpening ? "==new" + tag + "==>" : "<==new==")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList(original.split("\n")),
|
||||
Arrays.asList(revised.split("\n")));
|
||||
|
||||
assertThat(rows).hasSize(13);
|
||||
|
||||
rows.stream()
|
||||
.filter(item -> item.getTag() != DiffRow.Tag.EQUAL)
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue188HangOnExamples() throws IOException, URISyntaxException {
|
||||
try (FileSystem zipFs = FileSystems.newFileSystem(Paths.get("target/test-classes/com/github/difflib/text/test.zip"), null);) {
|
||||
List<String> original = Files.readAllLines(zipFs.getPath("old.html"));
|
||||
List<String> revised = Files.readAllLines(zipFs.getPath("new.html"));
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.lineNormalizer(line -> line)
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.decompressDeltas(true)
|
||||
.oldTag(f -> f ? "<s style=\"background-color: #bbbbbb\">" : "</s>")
|
||||
.newTag(f -> f ? "<b style=\"background-color: #aaffaa\">" : "</b>")
|
||||
.build();
|
||||
|
||||
//List<DiffRow> rows = generator.generateDiffRows(original, revised);
|
||||
List<DiffRow> rows = generator.generateDiffRows(original, DiffUtils.diff(original, revised, new MyersDiffWithLinearSpace<>() ));
|
||||
|
||||
System.out.println(rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ public class UnifiedDiffReaderTest {
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo(".vhd");
|
||||
assertThat(file1.getFromFile()).isEqualTo("a.vhd");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getTail()).isNull();
|
||||
@@ -277,12 +277,44 @@ public class UnifiedDiffReaderTest {
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
final UnifiedDiffFile file = diff.getFiles().get(0);
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("Main.java");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue107_3() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue107_3.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("Billion laughs attack.md");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue107_4() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue107_4.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(27);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("README.md");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue107_5() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue107_5.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(22);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue110() throws IOException {
|
||||
@@ -332,4 +364,86 @@ public class UnifiedDiffReaderTest {
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue122() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue122.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("coders/wpg.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue123() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue123.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue141() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue141.diff"));
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getFromFile()).isEqualTo("a.txt");
|
||||
assertThat(file1.getToFile()).isEqualTo("a1.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue182add() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue182_add.diff"));
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getBinaryAdded()).isEqualTo("some-image.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue182delete() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue182_delete.diff"));
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getBinaryDeleted()).isEqualTo("some-image.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue182edit() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue182_edit.diff"));
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getBinaryEdited()).isEqualTo("some-image.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue182mode() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue182_mode.diff"));
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getOldMode()).isEqualTo("100644");
|
||||
assertThat(file1.getNewMode()).isEqualTo("100755");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue193Copy() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_parsing_issue193.diff"));
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getCopyFrom()).isEqualTo("modules/configuration/config/web/pcf/account/AccountContactCV.pcf");
|
||||
assertThat(file1.getCopyTo()).isEqualTo("modules/configuration/config/web/pcf/account/AccountContactCV.default.pcf");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2022 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.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@Disabled("for next release")
|
||||
public class UnifiedDiffRoundTripNewLineTest {
|
||||
@Test
|
||||
public void testIssue135MissingNoNewLineInPatched() throws IOException, PatchFailedException {
|
||||
String beforeContent = "rootProject.name = \"sample-repo\"";
|
||||
String afterContent = "rootProject.name = \"sample-repo\"\n";
|
||||
String patch = "diff --git a/settings.gradle b/settings.gradle\n" +
|
||||
"index ef3b8e2..ab30124 100644\n" +
|
||||
"--- a/settings.gradle\n" +
|
||||
"+++ b/settings.gradle\n" +
|
||||
"@@ -1 +1 @@\n" +
|
||||
"-rootProject.name = \"sample-repo\"\n" +
|
||||
"\\ No newline at end of file\n" +
|
||||
"+rootProject.name = \"sample-repo\"\n";
|
||||
UnifiedDiff unifiedDiff = UnifiedDiffReader.parseUnifiedDiff(new ByteArrayInputStream(patch.getBytes()));
|
||||
String unifiedAfterContent = unifiedDiff.getFiles().get(0).getPatch()
|
||||
.applyTo(Arrays.asList(beforeContent.split("\n"))).stream().collect(joining("\n"));
|
||||
assertEquals(afterContent, unifiedAfterContent);
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class UnifiedDiffRoundTripTest {
|
||||
// Patch<String> fromUnifiedPatch = unifiedDiff.getFiles().get(0).getPatch();
|
||||
// patchedLines = fromUnifiedPatch.applyTo(origLines);
|
||||
// }
|
||||
patchedLines = unifiedDiff.spplyPatchTo(file -> originalFile.equals(file), origLines);
|
||||
patchedLines = unifiedDiff.applyPatchTo(file -> originalFile.equals(file), origLines);
|
||||
assertEquals(revLines.size(), patchedLines.size());
|
||||
for (int i = 0; i < revLines.size(); i++) {
|
||||
String l1 = revLines.get(i);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated
|
||||
to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or
|
||||
any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to
|
||||
dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live.
|
||||
It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate -- we can not
|
||||
consecrate -- we can not hallow -- this ground. The brave men, living and dead, who struggled here, have consecrated it,
|
||||
far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never
|
||||
forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought
|
||||
here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us -- that
|
||||
from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion -- that
|
||||
we here highly resolve that these dead shall not have died in vain -- that this nation, under God, shall have a new birth of
|
||||
freedom -- and that government of the people, by the people, for the people, shall not perish from the earth.
|
||||
@@ -0,0 +1,13 @@
|
||||
Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and
|
||||
dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether
|
||||
that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that
|
||||
war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives
|
||||
that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we
|
||||
can not dedicate -- we can not consecrate -- we can not hallow -- this ground. The brave men, living and dead, who
|
||||
struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long
|
||||
remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated
|
||||
here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here
|
||||
dedicated to the great task remaining before us -- that from these honored dead we take increased devotion to that cause
|
||||
for which they gave the last full measure of devotion -- that we here highly resolve that these dead shall not have died
|
||||
in vain -- that this nation, under God, shall have a new birth of freedom -- and that government of the people, by the
|
||||
people, for the people, shall not perish from the earth.
|
||||
@@ -0,0 +1,19 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nec mattis ipsum. Aliquam faucibus, augue quis faucibus scelerisque, sapien eros consequat erat, in semper quam nisi id ex. In viverra pulvinar tortor, non mollis eros ornare a. Praesent sagittis tincidunt ante, sed vulputate tellus faucibus quis. Sed efficitur, mi eu fringilla lobortis, lacus nisl aliquet ante, nec fermentum felis dui vel nunc. Fusce luctus rutrum ligula, sit amet suscipit est sollicitudin at. Suspendisse convallis ac dui a porttitor. Ut eget efficitur odio. In a facilisis quam, in imperdiet libero. Cras a orci in mi accumsan elementum. Duis at venenatis neque. Sed vel tellus ex.
|
||||
|
||||
Nam non velit at nunc tempus cursus ut vel ipsum. Nam nec nisi a nisl pellentesque faucibus ut et purus. Nulla in felis efficitur, facilisis turpis volutpat, consequat nisi. Vivamus ullamcorper euismod ex, et lobortis erat tristique id. Etiam rhoncus ante non eros lacinia, in porttitor lorem blandit. Duis porta malesuada blandit. Suspendisse tincidunt id dolor non semper. Morbi et enim sem. Proin vitae elit purus. Phasellus vel enim eget nisl tristique fringilla ac sit amet leo. In malesuada commodo condimentum. Aliquam erat volutpat. Curabitur et nibh nulla. In accumsan odio vel tortor semper euismod. Vivamus ex orci, elementum id pellentesque nec, blandit imperdiet magna.
|
||||
|
||||
Fusce congue lectus pulvinar odio finibus semper. Donec id quam dignissim, suscipit elit pharetra, scelerisque enim. Cras sit amet consectetur nisl. Fusce ornare velit lectus, a volutpat est finibus quis. Vestibulum dui odio, facilisis vel neque eu, blandit placerat purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent quis nunc fermentum, rutrum velit nec, feugiat odio. Quisque euismod nunc eu orci pharetra, eu egestas lectus hendrerit. Vivamus interdum, felis ac fringilla volutpat, elit purus rhoncus dui, ac vulputate turpis elit a nunc. Integer et nisl quis sapien euismod tempus. Duis feugiat leo a ipsum aliquam elementum nec non sapien. Mauris egestas lorem fermentum nisi mollis consequat. Donec velit elit, ornare vel erat at, placerat consequat ex.
|
||||
|
||||
Sed gravida fermentum sapien, nec finibus odio imperdiet eu. Phasellus ornare non dui ac blandit. Fusce eu tristique dolor. Vivamus non interdum nisl. Mauris feugiat euismod purus sit amet bibendum. Nullam sit amet libero nec dui viverra lobortis. Phasellus quis velit in risus maximus fringilla.
|
||||
|
||||
Nullam sed ipsum mollis ante lacinia ornare sed quis massa. Pellentesque finibus accumsan odio commodo fermentum. Morbi malesuada tincidunt tellus sit amet interdum. Cras consequat posuere maximus. In mauris metus, ornare vel augue id, ornare aliquam leo. Sed sapien mauris, laoreet rhoncus pharetra eget, placerat vel quam. Curabitur congue varius tellus vel porttitor. Ut ornare semper sem, et maximus dolor eleifend quis. Ut fringilla est diam, eget euismod justo tempus at. Nulla egestas, dolor a mollis imperdiet, velit ligula porta urna, nec laoreet nisl neque convallis turpis. Nulla non blandit lectus.
|
||||
|
||||
Nunc gravida est ipsum, in mattis purus ultrices ac. Cras ultrices nulla interdum, pulvinar urna imperdiet, egestas dui. Morbi vitae euismod ex. In gravida id elit in ullamcorper. Sed nisl lacus, tristique ut dapibus in, mattis tristique quam. Nam pulvinar in purus id lacinia. Nulla faucibus orci elementum neque feugiat cursus. Fusce quis faucibus turpis. Phasellus eleifend rutrum elit, at viverra erat consequat id. Suspendisse vehicula, dui et dapibus tincidunt, metus metus sagittis sapien, ut sagittis neque urna ac lectus. Phasellus eleifend, augue ut facilisis elementum, quam nisi ornare diam, sit amet accumsan leo justo id augue. Aenean feugiat, leo vitae semper rutrum, velit odio vulputate enim, eget finibus dui eros in dui. Aenean aliquet metus sed est malesuada, sit amet posuere purus rutrum. Ut sed iaculis mauris. Proin at arcu congue, auctor diam pulvinar, iaculis magna.
|
||||
|
||||
Suspendisse faucibus dapibus nisl, imperdiet tristique nibh lobortis sodales. Integer pretium laoreet dui non molestie. Morbi dignissim sit amet ex at semper. Proin venenatis augue quis magna aliquam, molestie ultricies sem auctor. Nulla ullamcorper eros dolor, at efficitur nunc egestas id. Integer leo eros, suscipit pharetra pharetra fringilla, tempus sed quam. Nam eu fringilla metus. Quisque in dolor turpis.
|
||||
|
||||
Integer faucibus ligula at vulputate mattis. Donec in fringilla metus, vel consequat dui. Pellentesque et maximus massa. Aenean iaculis, neque in vestibulum gravida, ligula lorem interdum libero, ut luctus justo purus a neque. Fusce luctus placerat hendrerit. Integer tempor, nibh eget viverra bibendum, massa est lobortis lectus, et pretium mi odio eu justo. Suspendisse et commodo eros. Quisque consectetur quam libero, nec pulvinar nunc lacinia eget. Nunc vulputate blandit risus, vitae viverra ante pharetra id.
|
||||
|
||||
Mauris convallis neque id hendrerit elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales orci felis, rutrum dapibus velit sodales vitae. Donec rhoncus fringilla neque sit amet blandit. Donec vel nisl volutpat, porta ligula a, dignissim massa. Praesent varius, orci a congue lobortis, nisi odio finibus felis, finibus gravida ligula ipsum maximus eros. Vestibulum id diam ac augue lobortis molestie. In hac habitasse platea dictumst. Quisque vulputate maximus gravida. Donec lobortis, velit in tempus cursus, sapien libero cursus ante, at ornare arcu massa id risus. Etiam metus erat, commodo vitae sodales sed, dignissim a metus. Aliquam eros ligula, dictum sit amet quam ullamcorper, iaculis congue quam. Vestibulum sollicitudin interdum enim vel aliquam. Fusce et leo sit amet nibh consectetur fringilla.
|
||||
|
||||
Nullam ultrices est tincidunt turpis pellentesque, eget dapibus quam laoreet. Maecenas convallis suscipit nunc sed dignissim. Aliquam ex turpis, congue quis porttitor quis, efficitur nec sapien. Vivamus mattis elementum posuere. Aenean quis eros vitae sapien rhoncus posuere. Donec ultricies elit sed arcu ultrices imperdiet ut quis sem. Nullam sit amet mauris suscipit, porta massa at, porttitor leo. Duis tempor purus nec mollis pretium. Ut bibendum posuere mollis. Nulla vehicula, sapien id bibendum eleifend, ipsum est rhoncus ante, eget pulvinar justo magna a ante. Sed luctus arcu hendrerit, auctor sem ac, rhoncus tellus. Integer eu quam scelerisque, eleifend massa eu, congue sem.
|
||||
@@ -0,0 +1,13 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nec mattis ipsum. Aliquam faucibus, augue quis faucibus scelerisque, sapien eros consequat erat, in semper quam nisi id ex. In viverra pulvinar tortor, non mollis eros ornare a. Praesent sagittis tincidunt ante, sed vulputate tellus faucibus quis. Sed efficitur, mi eu fringilla lobortis, lacus nisl aliquet ante, nec fermentum felis dui vel nunc. Fusce luctus rutrum ligula, sit amet suscipit est sollicitudin at. Suspendisse convallis ac dui a porttitor. Ut eget efficitur odio. In a facilisis quam, in imperdiet libero. Cras a orci in mi accumsan elementum. Duis at venenatis neque. Sed vel tellus ex.
|
||||
|
||||
Nam non velit at nunc tempus cursus ut vel ipsum. Nam nec nisi a nisl pellentesque faucibus ut et purus. Nulla in felis efficitur, facilisis turpis volutpat, consequat nisi. Vivamus ullamcorper euismod ex, et lobortis erat tristique id. Etiam rhoncus ante non eros lacinia, in porttitor lorem blandit. Duis porta malesuada blandit. Suspendisse tincidunt id dolor non semper. Morbi et enim sem. Proin vitae elit purus. Phasellus vel enim eget nisl tristique fringilla ac sit amet leo. In malesuada commodo condimentum. Aliquam erat volutpat. Curabitur et nibh nulla. In accumsan odio vel tortor semper euismod. Vivamus ex orci, elementum id pellentesque nec, blandit imperdiet magna.
|
||||
|
||||
Fusce congue lectus pulvinar odio finibus semper. Donec id quam dignissim, suscipit elit pharetra, scelerisque enim. Cras sit amet consectetur nisl. Fusce ornare velit lectus, a volutpat est finibus quis. Vestibulum dui odio, facilisis vel neque eu, blandit placerat purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent quis nunc fermentum, rutrum velit nec, feugiat odio. Quisque euismod nunc eu orci pharetra, eu egestas lectus hendrerit. Vivamus interdum, felis ac fringilla volutpat, elit purus rhoncus dui, ac vulputate turpis elit a nunc. Integer et nisl quis sapien euismod tempus. Duis feugiat leo a ipsum aliquam elementum nec non sapien. Mauris egestas lorem fermentum nisi mollis consequat. Donec velit elit, ornare vel erat at, placerat consequat ex.
|
||||
|
||||
Sed gravida fermentum sapien, nec finibus odio imperdiet eu. Phasellus ornare non dui ac blandit. Fusce eu tristique dolor. Vivamus non interdum nisl. Mauris feugiat euismod purus sit amet bibendum. Nullam sit amet libero nec dui viverra lobortis. Phasellus quis velit in risus maximus fringilla.
|
||||
|
||||
Nullam sed ipsum mollis ante lacinia ornare sed quis massa. Pellentesque finibus accumsan odio commodo fermentum. Morbi malesuada tincidunt tellus sit amet interdum. Cras consequat posuere maximus. In mauris metus, ornare vel augue id, ornare aliquam leo. Sed sapien mauris, laoreet rhoncus pharetra eget, placerat vel quam. Curabitur congue varius tellus vel porttitor. Ut ornare semper sem, et maximus dolor eleifend quis. Ut fringilla est diam, eget euismod justo tempus at. Nulla egestas, dolor a mollis imperdiet, velit ligula porta urna, nec laoreet nisl neque convallis turpis. Nulla non blandit lectus.
|
||||
|
||||
Mauris convallis neque id hendrerit elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales orci felis, rutrum dapibus velit sodales vitae. Donec rhoncus fringilla neque sit amet blandit. Donec vel nisl volutpat, porta ligula a, dignissim massa. Praesent varius, orci a congue lobortis, nisi odio finibus felis, finibus gravida ligula ipsum maximus eros. Vestibulum id diam ac augue lobortis molestie. In hac habitasse platea dictumst. Quisque vulputate maximus gravida. Donec lobortis, velit in tempus cursus, sapien libero cursus ante, at ornare arcu massa id risus. Etiam metus erat, commodo vitae sodales sed, dignissim a metus. Aliquam eros ligula, dictum sit amet quam ullamcorper, iaculis congue quam. Vestibulum sollicitudin interdum enim vel aliquam. Fusce et leo sit amet nibh consectetur fringilla.
|
||||
|
||||
Nullam ultrices est tincidunt turpis pellentesque, eget dapibus quam laoreet. Maecenas convallis suscipit nunc sed dignissim. Aliquam ex turpis, congue quis porttitor quis, efficitur nec sapien. Vivamus mattis elementum posuere. Aenean quis eros vitae sapien rhoncus posuere. Donec ultricies elit sed arcu ultrices imperdiet ut quis sem. Nulla vehicula, sapien id bibendum eleifend, ipsum est rhoncus ante, eget pulvinar justo magna a ante. Sed luctus arcu hendrerit, auctor sem ac, rhoncus tellus. Integer eu quam scelerisque, eleifend massa eu, congue sem.
|
||||
@@ -0,0 +1,19 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nec mattis ipsum. Aliquam faucibus, augue quis faucibus scelerisque, sapien eros consequat erat, in semper quam nisi id ex. In viverra pulvinar tortor, non mollis eros ornare a. Praesent sagittis tincidunt ante, sed vulputate tellus faucibus quis. Sed efficitur, mi eu fringilla lobortis, lacus nisl aliquet ante, nec fermentum felis dui vel nunc. Fusce luctus rutrum ligula, sit amet suscipit est sollicitudin at. Suspendisse convallis ac dui a porttitor. Ut eget efficitur odio. In a facilisis quam, in imperdiet libero. Cras a orci in mi accumsan elementum. Duis at venenatis neque. Sed vel tellus ex.
|
||||
|
||||
Nam non velit at nunc tempus cursus ut vel ipsum. Nam nec nisi a nisl pellentesque faucibus ut et purus. Nulla in felis efficitur, facilisis turpis volutpat, consequat nisi. Vivamus ullamcorper euismod ex, et lobortis erat tristique id. Etiam rhoncus ante non eros lacinia, in porttitor lorem blandit. Duis porta malesuada blandit. Suspendisse tincidunt id dolor non semper. Morbi et enim sem. Proin vitae elit purus. Phasellus vel enim eget nisl tristique fringilla ac sit amet leo. In malesuada commodo condimentum. Aliquam erat volutpat. Curabitur et nibh nulla. In accumsan odio vel tortor semper euismod. Vivamus ex orci, elementum id pellentesque nec, blandit imperdiet magna.
|
||||
|
||||
Fusce congue lectus pulvinar odio finibus semper. Donec id quam dignissim, suscipit elit pharetra, scelerisque enim. Cras sit amet consectetur nisl. Fusce ornare velit lectus, a volutpat est finibus quis. Vestibulum dui odio, facilisis vel neque eu, blandit placerat purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent quis nunc fermentum, rutrum velit nec, feugiat odio. Quisque euismod nunc eu orci pharetra, eu egestas lectus hendrerit. Vivamus interdum, felis ac fringilla volutpat, elit purus rhoncus dui, ac vulputate turpis elit a nunc. Integer et nisl quis sapien euismod tempus. Duis feugiat leo a ipsum aliquam elementum nec non sapien. Mauris egestas lorem fermentum nisi mollis consequat. Donec velit elit, ornare vel erat at, placerat consequat ex.
|
||||
|
||||
Sed gravida fermentum sapien, nec finibus odio imperdiet eu. Phasellus ornare non dui ac blandit. Fusce eu tristique dolor. Vivamus non interdum nisl. Mauris feugiat euismod purus sit amet bibendum. Nullam sit amet libero nec dui viverra lobortis. Phasellus quis velit in risus maximus fringilla.
|
||||
|
||||
Nullam sed ipsum mollis ante lacinia ornare sed quis massa. Pellentesque finibus accumsan odio commodo fermentum. Morbi malesuada tincidunt tellus sit amet interdum. Cras consequat posuere maximus. In mauris metus, ornare vel augue id, ornare aliquam leo. Sed sapien mauris, laoreet rhoncus pharetra eget, placerat vel quam. Curabitur congue varius tellus vel porttitor. Ut ornare semper sem, et maximus dolor eleifend quis. Ut fringilla est diam, eget euismod justo tempus at. Nulla egestas, dolor a mollis imperdiet, velit ligula porta urna, nec laoreet nisl neque convallis turpis. Nulla non blandit lectus.
|
||||
|
||||
Nunc gravida est ipsum, in mattis purus ultrices ac. Cras ultrices nulla interdum, pulvinar urna imperdiet, egestas dui. Morbi vitae euismod ex. In gravida id elit in ullamcorper. Sed nisl lacus, tristique ut dapibus in, mattis tristique quam. Nam pulvinar in purus id lacinia. Nulla faucibus orci elementum neque feugiat cursus. Fusce quis faucibus turpis. Phasellus eleifend rutrum elit, at viverra erat consequat id. Suspendisse vehicula, dui et dapibus tincidunt, metus metus sagittis sapien, ut sagittis neque urna ac lectus. Phasellus eleifend, augue ut facilisis elementum, quam nisi ornare diam, sit amet accumsan leo justo id augue. Aenean feugiat, leo vitae semper rutrum, velit odio vulputate enim, eget finibus dui eros in dui. Aenean aliquet metus sed est malesuada, sit amet posuere purus rutrum. Ut sed iaculis mauris. Proin at arcu congue, auctor diam pulvinar, iaculis magna.
|
||||
|
||||
Suspendisse faucibus dapibus nisl, imperdiet tristique nibh lobortis sodales. Integer pretium laoreet dui non molestie. Morbi dignissim sit amet ex at semper. Proin venenatis augue quis magna aliquam, molestie ultricies sem auctor. Nulla ullamcorper eros dolor, at efficitur nunc egestas id. Integer leo eros, suscipit pharetra pharetra fringilla, tempus sed quam. Nam eu fringilla metus. Quisque in dolor turpis.
|
||||
|
||||
Integer faucibus ligula at vulputate mattis. Donec in fringilla metus, vel consequat dui. Pellentesque et maximus massa. Aenean iaculis, neque in vestibulum gravida, ligula lorem interdum libero, ut luctus justo purus a neque. Fusce luctus placerat hendrerit. Integer tempor, nibh eget viverra bibendum, massa est lobortis lectus, et pretium mi odio eu justo. Suspendisse et commodo eros. Quisque consectetur quam libero, nec pulvinar nunc lacinia eget. Nunc vulputate blandit risus, vitae viverra ante pharetra id.
|
||||
|
||||
Mauris convallis neque id hendrerit elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales orci felis, rutrum dapibus velit sodales vitae. Donec rhoncus fringilla neque sit amet blandit. Donec vel nisl volutpat, porta ligula a, dignissim massa. Praesent varius, orci a congue lobortis, nisi odio finibus felis, finibus gravida ligula ipsum maximus eros. Vestibulum id diam ac augue lobortis molestie. In hac habitasse platea dictumst. Quisque vulputate maximus gravida. Donec lobortis, velit in tempus cursus, sapien libero cursus ante, at ornare arcu massa id risus. Etiam metus erat, commodo vitae sodales sed, dignissim a metus. Aliquam eros ligula, dictum sit amet quam ullamcorper, iaculis congue quam. Vestibulum sollicitudin interdum enim vel aliquam. Fusce et leo sit amet nibh consectetur fringilla.
|
||||
|
||||
Nullam ultrices est tincidunt turpis pellentesque, eget dapibus quam laoreet. Maecenas convallis suscipit nunc sed dignissim. Aliquam ex turpis, congue quis porttitor quis, efficitur nec sapien. Vivamus mattis elementum posuere. Aenean quis eros vitae sapien rhoncus posuere. Donec ultricies elit sed arcu ultrices imperdiet ut quis sem. Nullam sit amet mauris suscipit, porta massa at, porttitor leo. Duis tempor purus nec mollis pretium. Ut bibendum posuere mollis. Nulla vehicula, sapien id bibendum eleifend, ipsum est rhoncus ante, eget pulvinar justo magna a ante. Sed luctus arcu hendrerit, auctor sem ac, rhoncus tellus. Integer eu quam scelerisque, eleifend massa eu, congue sem.
|
||||
@@ -0,0 +1,25 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nec mattis ipsum. Aliquam faucibus, augue quis faucibus scelerisque, sapien eros consequat erat, in semper quam nisi id ex. In viverra pulvinar tortor, non mollis eros ornare a. Praesent sagittis tincidunt ante, sed vulputate tellus faucibus quis. Sed efficitur, mi eu fringilla lobortis, lacus nisl aliquet ante, nec fermentum felis dui vel nunc. Fusce luctus rutrum ligula, sit amet suscipit est sollicitudin at. Suspendisse convallis ac dui a porttitor. Ut eget efficitur odio. In a facilisis quam, in imperdiet libero. Cras a orci in mi accumsan elementum. Duis at venenatis neque. Sed vel tellus ex.
|
||||
|
||||
Nam non velit at nunc tempus cursus ut vel ipsum. Nam nec nisi a nisl pellentesque faucibus ut et purus. Nulla in felis efficitur, facilisis turpis volutpat, consequat nisi. Vivamus ullamcorper euismod ex, et lobortis erat tristique id. Etiam rhoncus ante non eros lacinia, in porttitor lorem blandit. Duis porta malesuada blandit. Suspendisse tincidunt id dolor non semper. Morbi et enim sem. Proin vitae elit purus. Phasellus vel enim eget nisl tristique fringilla ac sit amet leo. In malesuada commodo condimentum. Aliquam erat volutpat. Curabitur et nibh nulla. In accumsan odio vel tortor semper euismod. Vivamus ex orci, elementum id pellentesque nec, blandit imperdiet magna.
|
||||
|
||||
Fusce congue lectus pulvinar odio finibus semper. Donec id quam dignissim, suscipit elit pharetra, scelerisque enim. Cras sit amet consectetur nisl. Fusce ornare velit lectus, a volutpat est finibus quis. Vestibulum dui odio, facilisis vel neque eu, blandit placerat purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent quis nunc fermentum, rutrum velit nec, feugiat odio. Quisque euismod nunc eu orci pharetra, eu egestas lectus hendrerit. Vivamus interdum, felis ac fringilla volutpat, elit purus rhoncus dui, ac vulputate turpis elit a nunc. Integer et nisl quis sapien euismod tempus. Duis feugiat leo a ipsum aliquam elementum nec non sapien. Mauris egestas lorem fermentum nisi mollis consequat. Donec velit elit, ornare vel erat at, placerat consequat ex.
|
||||
|
||||
Sed gravida fermentum sapien, nec finibus odio imperdiet eu. Phasellus ornare non dui ac blandit. Fusce eu tristique dolor. Vivamus non interdum nisl. Mauris feugiat euismod purus sit amet bibendum. Nullam sit amet libero nec dui viverra lobortis. Phasellus quis velit in risus maximus fringilla.
|
||||
|
||||
Nullam sed ipsum mollis ante lacinia ornare sed quis massa. Pellentesque finibus accumsan odio commodo fermentum. Morbi malesuada tincidunt tellus sit amet interdum. Cras consequat posuere maximus. In mauris metus, ornare vel augue id, ornare aliquam leo. Sed sapien mauris, laoreet rhoncus pharetra eget, placerat vel quam. Curabitur congue varius tellus vel porttitor. Ut ornare semper sem, et maximus dolor eleifend quis. Ut fringilla est diam, eget euismod justo tempus at. Nulla egestas, dolor a mollis imperdiet, velit ligula porta urna, nec laoreet nisl neque convallis turpis. Nulla non blandit lectus.
|
||||
|
||||
Nunc gravida est ipsum, in mattis purus ultrices ac. Cras ultrices nulla interdum, pulvinar urna imperdiet, egestas dui. Morbi vitae euismod ex. In gravida id elit in ullamcorper. Sed nisl lacus, tristique ut dapibus in, mattis tristique quam. Nam pulvinar in purus id lacinia. Nulla faucibus orci elementum neque feugiat cursus. Fusce quis faucibus turpis. Phasellus eleifend rutrum elit, at viverra erat consequat id. Suspendisse vehicula, dui et dapibus tincidunt, metus metus sagittis sapien, ut sagittis neque urna ac lectus. Phasellus eleifend, augue ut facilisis elementum, quam nisi ornare diam, sit amet accumsan leo justo id augue. Aenean feugiat, leo vitae semper rutrum, velit odio vulputate enim, eget finibus dui eros in dui. Aenean aliquet metus sed est malesuada, sit amet posuere purus rutrum. Ut sed iaculis mauris. Proin at arcu congue, auctor diam pulvinar, iaculis magna.
|
||||
|
||||
Sed gravida fermentum sapien, nec finibus odio imperdiet eu. Phasellus ornare non dui ac blandit. Fusce eu tristique dolor. Vivamus non interdum nisl. Mauris feugiat euismod purus sit amet bibendum. Nullam sit amet libero nec dui viverra lobortis. Phasellus quis velit in risus maximus fringilla.
|
||||
|
||||
Nullam sed ipsum mollis ante lacinia ornare sed quis massa. Pellentesque finibus accumsan odio commodo fermentum. Morbi malesuada tincidunt tellus sit amet interdum. Cras consequat posuere maximus. In mauris metus, ornare vel augue id, ornare aliquam leo. Sed sapien mauris, laoreet rhoncus pharetra eget, placerat vel quam. Curabitur congue varius tellus vel porttitor. Ut ornare semper sem, et maximus dolor eleifend quis. Ut fringilla est diam, eget euismod justo tempus at. Nulla egestas, dolor a mollis imperdiet, velit ligula porta urna, nec laoreet nisl neque convallis turpis. Nulla non blandit lectus.
|
||||
|
||||
Mauris convallis neque id hendrerit elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales orci felis, rutrum dapibus velit sodales vitae. Donec rhoncus fringilla neque sit amet blandit. Donec vel nisl volutpat, porta ligula a, dignissim massa. Praesent varius, orci a congue lobortis, nisi odio finibus felis, finibus gravida ligula ipsum maximus eros. Vestibulum id diam ac augue lobortis molestie. In hac habitasse platea dictumst. Quisque vulputate maximus gravida. Donec lobortis, velit in tempus cursus, sapien libero cursus ante, at ornare arcu massa id risus. Etiam metus erat, commodo vitae sodales sed, dignissim a metus. Aliquam eros ligula, dictum sit amet quam ullamcorper, iaculis congue quam. Vestibulum sollicitudin interdum enim vel aliquam. Fusce et leo sit amet nibh consectetur fringilla.
|
||||
|
||||
Suspendisse faucibus dapibus nisl, imperdiet tristique nibh lobortis sodales. Integer pretium laoreet dui non molestie. Morbi dignissim sit amet ex at semper. Proin venenatis augue quis magna aliquam, molestie ultricies sem auctor. Nulla ullamcorper eros dolor, at efficitur nunc egestas id. Integer leo eros, suscipit pharetra pharetra fringilla, tempus sed quam. Nam eu fringilla metus. Quisque in dolor turpis.
|
||||
|
||||
Integer faucibus ligula at vulputate mattis. Donec in fringilla metus, vel consequat dui. Pellentesque et maximus massa. Aenean iaculis, neque in vestibulum gravida, ligula lorem interdum libero, ut luctus justo purus a neque. Fusce luctus placerat hendrerit. Integer tempor, nibh eget viverra bibendum, massa est lobortis lectus, et pretium mi odio eu justo. Suspendisse et commodo eros. Quisque consectetur quam libero, nec pulvinar nunc lacinia eget. Nunc vulputate blandit risus, vitae viverra ante pharetra id.
|
||||
|
||||
Mauris convallis neque id hendrerit elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales orci felis, rutrum dapibus velit sodales vitae. Donec rhoncus fringilla neque sit amet blandit. Donec vel nisl volutpat, porta ligula a, dignissim massa. Praesent varius, orci a congue lobortis, nisi odio finibus felis, finibus gravida ligula ipsum maximus eros. Vestibulum id diam ac augue lobortis molestie. In hac habitasse platea dictumst. Quisque vulputate maximus gravida. Donec lobortis, velit in tempus cursus, sapien libero cursus ante, at ornare arcu massa id risus. Etiam metus erat, commodo vitae sodales sed, dignissim a metus. Aliquam eros ligula, dictum sit amet quam ullamcorper, iaculis congue quam. Vestibulum sollicitudin interdum enim vel aliquam. Fusce et leo sit amet nibh consectetur fringilla.
|
||||
|
||||
Nullam ultrices est tincidunt turpis pellentesque, eget dapibus quam laoreet. Maecenas convallis suscipit nunc sed dignissim. Aliquam ex turpis, congue quis porttitor quis, efficitur nec sapien. Vivamus mattis elementum posuere. Aenean quis eros vitae sapien rhoncus posuere. Donec ultricies elit sed arcu ultrices imperdiet ut quis sem. Nullam sit amet mauris suscipit, porta massa at, porttitor leo. Duis tempor purus nec mollis pretium. Ut bibendum posuere mollis. Nulla vehicula, sapien id bibendum eleifend, ipsum est rhoncus ante, eget pulvinar justo magna a ante. Sed luctus arcu hendrerit, auctor sem ac, rhoncus tellus. Integer eu quam scelerisque, eleifend massa eu, congue sem.
|
||||
Binary file not shown.
@@ -0,0 +1,24 @@
|
||||
diff -r 4d1de0a006b7 -r ace1482360cb Billion laughs attack.md
|
||||
--- a/Billion laughs attack.md Mon Feb 24 13:37:17 2020 +0000
|
||||
+++ b/Billion laughs attack.md Mon Feb 24 14:22:50 2020 +0000
|
||||
@@ -11,14 +11,12 @@
|
||||
|
||||
*The problem is*: when you stay with the mouth open and eyes closed then they may throw trash and you get sick.
|
||||
|
||||
-
|
||||
-SnakeYAML Engine [has a way to restrict the amount of aliases for collections](https://bitbucket.org/asomov/snakeyaml-engine/src/default/src/test/java/org/snakeyaml/engine/usecases/references/ReferencesTest.java) to fail early without allocation too much resources.
|
||||
+SnakeYAML 1.26+ [has a way to restrict the amount of aliases for collections](https://bitbucket.org/asomov/snakeyaml/src/default/src/test/java/org/yaml/snakeyaml/issues/issue377/ReferencesTest.java) to fail early without allocation too much resources.
|
||||
|
||||
# Solution #
|
||||
|
||||
-1. If the YAML is not coming from untrusted source (it is merely a configuration file) then it is a false positive. Just ignore it. The quality of NVD database is very low and contains tons of issues which appear to be false positives.
|
||||
-2. Migrate to [SnakeYAML Engine](https://bitbucket.org/asomov/snakeyaml-engine/src/default/). It has a configuration option to restrict aliases for collections (the aliases for scalars cannot grow and they are not restricted)
|
||||
-3. Check how it is done in SnakeYAML Engine and build your own SnakeYAML version with the same change.
|
||||
-4. Read the YAML and check its quality before giving the document to SnakeYAML (count `*` and `&` for instance)
|
||||
+1. Update to SnakeYAML 1.26. It has a configuration option to restrict aliases for collections (the aliases for scalars cannot grow and they are not restricted)
|
||||
+2. If the YAML is not coming from untrusted source (it is merely a configuration file) then it is a false positive. Just ignore it. The quality of NVD database is very low and contains tons of issues which appear to be false positives.
|
||||
+3. Read the YAML and check its quality before giving the document to SnakeYAML (count `*` and `&` for instance)
|
||||
|
||||
-Enjoy.
|
||||
\ No newline at end of file
|
||||
+Enjoy.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,835 @@
|
||||
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
|
||||
index 1f2a7c4baec..9d636200d61 100644
|
||||
--- a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
|
||||
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
|
||||
@@ -112,7 +112,6 @@ public static void main(String[] args) throws Exception {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("bus.jmx.usePlatformMBeanServer", Boolean.TRUE);
|
||||
properties.put("bus.jmx.enabled", Boolean.TRUE);
|
||||
- properties.put("bus.jmx.createMBServerConnectorFactory", Boolean.FALSE);
|
||||
Bus b = new CXFBusFactory().createBus(null, properties);
|
||||
MetricRegistry registry = new MetricRegistry();
|
||||
CodahaleMetricsProvider.setupJMXReporter(b, registry);
|
||||
diff --git a/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml b/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml
|
||||
index 8bf5109ec95..391f97c624e 100644
|
||||
--- a/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml
|
||||
+++ b/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml
|
||||
@@ -45,4 +45,4 @@
|
||||
<bean class="org.apache.cxf.ext.logging.LoggingFeature"/>
|
||||
</jaxws:features>
|
||||
</jaxws:endpoint>
|
||||
-</beans>
|
||||
\ No newline at end of file
|
||||
+</beans>
|
||||
diff --git a/rt/management/pom.xml b/rt/management/pom.xml
|
||||
index f63f3bfa6d7..19ccf6ada0c 100644
|
||||
--- a/rt/management/pom.xml
|
||||
+++ b/rt/management/pom.xml
|
||||
@@ -34,8 +34,7 @@
|
||||
<cxf.module.name>org.apache.cxf.management</cxf.module.name>
|
||||
<cxf.osgi.import>
|
||||
javax.xml.bind*;version="${cxf.osgi.javax.bind.version}",
|
||||
- javax.annotation*;version="${cxf.osgi.javax.annotation.version}",
|
||||
- sun.rmi*;resolution:=optional
|
||||
+ javax.annotation*;version="${cxf.osgi.javax.annotation.version}"
|
||||
</cxf.osgi.import>
|
||||
</properties>
|
||||
<dependencies>
|
||||
diff --git a/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java b/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java
|
||||
index ee7f0a71fee..d898a4b6f5f 100644
|
||||
--- a/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java
|
||||
+++ b/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package org.apache.cxf.management.jmx;
|
||||
|
||||
-import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -53,31 +52,25 @@
|
||||
import org.apache.cxf.management.ManagedComponent;
|
||||
import org.apache.cxf.management.ManagementConstants;
|
||||
import org.apache.cxf.management.jmx.export.runtime.ModelMBeanAssembler;
|
||||
-import org.apache.cxf.management.jmx.type.JMXConnectorPolicyType;
|
||||
|
||||
/**
|
||||
* The manager class for the JMXManagedComponent which hosts the JMXManagedComponents.
|
||||
*/
|
||||
-public class InstrumentationManagerImpl extends JMXConnectorPolicyType
|
||||
+public class InstrumentationManagerImpl
|
||||
implements InstrumentationManager, BusLifeCycleListener {
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(InstrumentationManagerImpl.class);
|
||||
|
||||
private static Map<String, String> mbeanServerIDMap = new HashMap<>();
|
||||
|
||||
private Bus bus;
|
||||
- private MBServerConnectorFactory mcf;
|
||||
private MBeanServer mbs;
|
||||
private Set<ObjectName> busMBeans = new HashSet<>();
|
||||
private boolean connectFailed;
|
||||
private String persistentBusId;
|
||||
- private Map<String, ?> environment;
|
||||
|
||||
- /**
|
||||
- * For backward compatibility, {@link #createMBServerConnectorFactory} is <code>true</code> by default.
|
||||
- */
|
||||
- private boolean createMBServerConnectorFactory = true;
|
||||
private String mbeanServerName = ManagementConstants.DEFAULT_DOMAIN_NAME;
|
||||
private boolean usePlatformMBeanServer;
|
||||
+ private boolean enabled;
|
||||
|
||||
public InstrumentationManagerImpl() {
|
||||
super();
|
||||
@@ -119,16 +112,16 @@ public void setServerName(String s) {
|
||||
mbeanServerName = s;
|
||||
}
|
||||
|
||||
- public void setCreateMBServerConnectorFactory(boolean createMBServerConnectorFactory) {
|
||||
- this.createMBServerConnectorFactory = createMBServerConnectorFactory;
|
||||
- }
|
||||
-
|
||||
public void setUsePlatformMBeanServer(Boolean flag) {
|
||||
usePlatformMBeanServer = flag;
|
||||
}
|
||||
|
||||
- public void setEnvironment(Map<String, ?> env) {
|
||||
- environment = env;
|
||||
+ public void setEnabled(boolean enabled) {
|
||||
+ this.enabled = enabled;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isEnabled() {
|
||||
+ return enabled;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -139,7 +132,6 @@ public void register() {
|
||||
public void init() {
|
||||
if (bus != null && bus.getExtension(MBeanServer.class) != null) {
|
||||
enabled = true;
|
||||
- createMBServerConnectorFactory = false;
|
||||
mbs = bus.getExtension(MBeanServer.class);
|
||||
}
|
||||
if (isEnabled()) {
|
||||
@@ -168,21 +160,6 @@ public void init() {
|
||||
}
|
||||
}
|
||||
|
||||
- if (createMBServerConnectorFactory) {
|
||||
- mcf = MBServerConnectorFactory.getInstance();
|
||||
- mcf.setMBeanServer(mbs);
|
||||
- mcf.setThreaded(isThreaded());
|
||||
- mcf.setDaemon(isDaemon());
|
||||
- mcf.setServiceUrl(getJMXServiceURL());
|
||||
- mcf.setEnvironment(environment);
|
||||
- try {
|
||||
- mcf.createConnector();
|
||||
- } catch (IOException ex) {
|
||||
- connectFailed = true;
|
||||
- LOG.log(Level.SEVERE, "START_CONNECTOR_FAILURE_MSG", new Object[] {ex});
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (!connectFailed && null != bus) {
|
||||
try {
|
||||
//Register Bus here since we can guarantee that Instrumentation
|
||||
@@ -282,14 +259,6 @@ public void shutdown() {
|
||||
return;
|
||||
}
|
||||
|
||||
- if (mcf != null) {
|
||||
- try {
|
||||
- mcf.destroy();
|
||||
- } catch (IOException ex) {
|
||||
- LOG.log(Level.SEVERE, "STOP_CONNECTOR_FAILURE_MSG", new Object[] {ex});
|
||||
- }
|
||||
- }
|
||||
-
|
||||
//Using the array to hold the busMBeans to avoid the CurrentModificationException
|
||||
Object[] mBeans = busMBeans.toArray();
|
||||
for (Object name : mBeans) {
|
||||
@@ -400,12 +369,7 @@ private void readJMXProperties(Bus b) {
|
||||
getBusProperty(b, "bus.jmx.serverName", mbeanServerName);
|
||||
usePlatformMBeanServer =
|
||||
getBusProperty(b, "bus.jmx.usePlatformMBeanServer", usePlatformMBeanServer);
|
||||
- createMBServerConnectorFactory =
|
||||
- getBusProperty(b, "bus.jmx.createMBServerConnectorFactory", createMBServerConnectorFactory);
|
||||
- daemon = getBusProperty(b, "bus.jmx.daemon", daemon);
|
||||
- threaded = getBusProperty(b, "bus.jmx.threaded", threaded);
|
||||
enabled = getBusProperty(b, "bus.jmx.enabled", enabled);
|
||||
- jmxServiceURL = getBusProperty(b, "bus.jmx.JMXServiceURL", jmxServiceURL);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/rt/management/src/main/java/org/apache/cxf/management/jmx/MBServerConnectorFactory.java b/rt/management/src/main/java/org/apache/cxf/management/jmx/MBServerConnectorFactory.java
|
||||
deleted file mode 100644
|
||||
index 5eb7059b8fb..00000000000
|
||||
--- a/rt/management/src/main/java/org/apache/cxf/management/jmx/MBServerConnectorFactory.java
|
||||
+++ /dev/null
|
||||
@@ -1,260 +0,0 @@
|
||||
-/**
|
||||
- * Licensed to the Apache Software Foundation (ASF) under one
|
||||
- * or more contributor license agreements. See the NOTICE file
|
||||
- * distributed with this work for additional information
|
||||
- * regarding copyright ownership. The ASF licenses this file
|
||||
- * to you 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 org.apache.cxf.management.jmx;
|
||||
-
|
||||
-import java.io.IOException;
|
||||
-import java.net.URI;
|
||||
-import java.net.URISyntaxException;
|
||||
-import java.rmi.AccessException;
|
||||
-import java.rmi.AlreadyBoundException;
|
||||
-import java.rmi.NotBoundException;
|
||||
-import java.rmi.Remote;
|
||||
-import java.rmi.RemoteException;
|
||||
-import java.util.Map;
|
||||
-import java.util.logging.Level;
|
||||
-import java.util.logging.Logger;
|
||||
-
|
||||
-import javax.management.MBeanServer;
|
||||
-import javax.management.MBeanServerFactory;
|
||||
-import javax.management.remote.JMXConnectorServer;
|
||||
-import javax.management.remote.JMXServiceURL;
|
||||
-import javax.management.remote.rmi.RMIConnectorServer;
|
||||
-import javax.management.remote.rmi.RMIJRMPServerImpl;
|
||||
-
|
||||
-import org.apache.cxf.common.logging.LogUtils;
|
||||
-
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Deal with the MBeanServer Connections
|
||||
- *
|
||||
- */
|
||||
-public final class MBServerConnectorFactory {
|
||||
-
|
||||
- public static final String DEFAULT_SERVICE_URL = "service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi";
|
||||
-
|
||||
- private static final Logger LOG = LogUtils.getL7dLogger(MBServerConnectorFactory.class);
|
||||
-
|
||||
- private static MBeanServer server;
|
||||
-
|
||||
- private static String serviceUrl = DEFAULT_SERVICE_URL;
|
||||
-
|
||||
- private static Map<String, ?> environment;
|
||||
-
|
||||
- private static boolean threaded;
|
||||
-
|
||||
- private static boolean daemon;
|
||||
-
|
||||
- private static JMXConnectorServer connectorServer;
|
||||
-
|
||||
- private static Remote remoteServerStub;
|
||||
-
|
||||
- private static RMIJRMPServerImpl rmiServer;
|
||||
-
|
||||
- private static class MBServerConnectorFactoryHolder {
|
||||
- private static final MBServerConnectorFactory INSTANCE =
|
||||
- new MBServerConnectorFactory();
|
||||
- }
|
||||
-
|
||||
- private static class MBeanServerHolder {
|
||||
- private static final MBeanServer INSTANCE =
|
||||
- MBeanServerFactory.createMBeanServer();
|
||||
- }
|
||||
-
|
||||
- private MBServerConnectorFactory() {
|
||||
-
|
||||
- }
|
||||
-
|
||||
- static int getServerPort(final String url) {
|
||||
- int portStart = url.indexOf("localhost") + 10;
|
||||
- int portEnd;
|
||||
- int port = 0;
|
||||
- if (portStart > 0) {
|
||||
- portEnd = indexNotOfNumber(url, portStart);
|
||||
- if (portEnd > portStart) {
|
||||
- final String portString = url.substring(portStart, portEnd);
|
||||
- port = Integer.parseInt(portString);
|
||||
- }
|
||||
- }
|
||||
- return port;
|
||||
- }
|
||||
-
|
||||
- private static int indexNotOfNumber(String str, int index) {
|
||||
- int i = 0;
|
||||
- for (i = index; i < str.length(); i++) {
|
||||
- if (str.charAt(i) < '0' || str.charAt(i) > '9') {
|
||||
- return i;
|
||||
- }
|
||||
- }
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- public static MBServerConnectorFactory getInstance() {
|
||||
- return MBServerConnectorFactoryHolder.INSTANCE;
|
||||
- }
|
||||
-
|
||||
- public void setMBeanServer(MBeanServer ms) {
|
||||
- server = ms;
|
||||
- }
|
||||
-
|
||||
- public void setServiceUrl(String url) {
|
||||
- serviceUrl = url;
|
||||
- }
|
||||
-
|
||||
- public void setEnvironment(Map<String, ?> env) {
|
||||
- environment = env;
|
||||
- }
|
||||
-
|
||||
- public void setThreaded(boolean fthread) {
|
||||
- threaded = fthread;
|
||||
- }
|
||||
-
|
||||
- public void setDaemon(boolean fdaemon) {
|
||||
- daemon = fdaemon;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- public void createConnector() throws IOException {
|
||||
-
|
||||
- if (server == null) {
|
||||
- server = MBeanServerHolder.INSTANCE;
|
||||
- }
|
||||
-
|
||||
- // Create the JMX service URL.
|
||||
- final JMXServiceURL url = new JMXServiceURL(serviceUrl);
|
||||
-
|
||||
- // if the URL is localhost, start up an Registry
|
||||
- if (serviceUrl.indexOf("localhost") > -1
|
||||
- && url.getProtocol().compareToIgnoreCase("rmi") == 0) {
|
||||
- try {
|
||||
- int port = getRegistryPort(serviceUrl);
|
||||
- new JmxRegistry(port, getBindingName(url));
|
||||
-
|
||||
- } catch (Exception ex) {
|
||||
- LOG.log(Level.SEVERE, "CREATE_REGISTRY_FAULT_MSG", new Object[]{ex});
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- rmiServer = new RMIJRMPServerImpl(getServerPort(serviceUrl), null, null, environment);
|
||||
-
|
||||
- // Create the connector server now.
|
||||
- connectorServer = new RMIConnectorServer(url, environment, rmiServer, server);
|
||||
-
|
||||
- if (threaded) {
|
||||
- // Start the connector server asynchronously (in a separate thread).
|
||||
- Thread connectorThread = new Thread() {
|
||||
- public void run() {
|
||||
- try {
|
||||
- connectorServer.start();
|
||||
- remoteServerStub = rmiServer.toStub();
|
||||
- } catch (IOException ex) {
|
||||
- LOG.log(Level.SEVERE, "START_CONNECTOR_FAILURE_MSG", new Object[]{ex});
|
||||
- }
|
||||
- }
|
||||
- };
|
||||
-
|
||||
- connectorThread.setName("JMX Connector Thread [" + serviceUrl + "]");
|
||||
- connectorThread.setDaemon(daemon);
|
||||
- connectorThread.start();
|
||||
- } else {
|
||||
- // Start the connector server in the same thread.
|
||||
- connectorServer.start();
|
||||
- remoteServerStub = rmiServer.toStub();
|
||||
- }
|
||||
-
|
||||
- if (LOG.isLoggable(Level.INFO)) {
|
||||
- LOG.info("JMX connector server started: " + connectorServer);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- static int getRegistryPort(final String url) {
|
||||
- int serverStart = url.indexOf("/jndi/rmi://");
|
||||
- final String serverPart = url.substring(serverStart + 12);
|
||||
- int portStart = serverPart.indexOf(':') + 1;
|
||||
-
|
||||
- int portEnd;
|
||||
- int port = 0;
|
||||
- if (portStart > 0) {
|
||||
- portEnd = indexNotOfNumber(serverPart, portStart);
|
||||
- if (portEnd > portStart) {
|
||||
- final String portString = serverPart.substring(portStart, portEnd);
|
||||
- port = Integer.parseInt(portString);
|
||||
- }
|
||||
- }
|
||||
- return port;
|
||||
- }
|
||||
-
|
||||
- protected static String getBindingName(final JMXServiceURL jmxServiceURL) {
|
||||
- final String urlPath = jmxServiceURL.getURLPath();
|
||||
-
|
||||
- try {
|
||||
- if (urlPath.startsWith("/jndi/")) {
|
||||
- return new URI(urlPath.substring(6)).getPath()
|
||||
- .replaceAll("^/+", "").replaceAll("/+$", "");
|
||||
- }
|
||||
- } catch (URISyntaxException e) {
|
||||
- // ignore
|
||||
- }
|
||||
-
|
||||
- return "jmxrmi"; // use the default
|
||||
- }
|
||||
-
|
||||
- public void destroy() throws IOException {
|
||||
- connectorServer.stop();
|
||||
- if (LOG.isLoggable(Level.INFO)) {
|
||||
- LOG.info("JMX connector server stopped: " + connectorServer);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Better to use the internal API than re-invent the wheel.
|
||||
- */
|
||||
- @SuppressWarnings("restriction")
|
||||
- private class JmxRegistry extends sun.rmi.registry.RegistryImpl {
|
||||
- private final String lookupName;
|
||||
-
|
||||
- JmxRegistry(final int port, final String lookupName) throws RemoteException {
|
||||
- super(port);
|
||||
- this.lookupName = lookupName;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public Remote lookup(String s) throws RemoteException, NotBoundException {
|
||||
- return lookupName.equals(s) ? remoteServerStub : null;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void bind(String s, Remote remote) throws RemoteException, AlreadyBoundException, AccessException {
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void unbind(String s) throws RemoteException, NotBoundException, AccessException {
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void rebind(String s, Remote remote) throws RemoteException, AccessException {
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public String[] list() throws RemoteException {
|
||||
- return new String[] {lookupName};
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
diff --git a/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java b/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java
|
||||
index 3fa2fe2891c..3739ffaa915 100644
|
||||
--- a/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java
|
||||
+++ b/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java
|
||||
@@ -42,7 +42,7 @@
|
||||
public final class ManagementConsole {
|
||||
private static MBeanServerConnection mbsc;
|
||||
private static final String DEFAULT_JMXSERVICE_URL =
|
||||
- "service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi";
|
||||
+ "service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi";
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(ManagementConsole.class);
|
||||
|
||||
String jmxServerURL;
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java b/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java
|
||||
index 9ebc7ca4fe2..c505835d10a 100644
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java
|
||||
+++ b/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java
|
||||
@@ -158,7 +158,6 @@ public void testInstrumentBusWithBusProperties() {
|
||||
assertNotNull("Instrumentation Manager of cxf1 should not be null", im1);
|
||||
|
||||
assertTrue(im1.isEnabled());
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi", im1.getJMXServiceURL());
|
||||
|
||||
cxf2 = (Bus)context.getBean("cxf2");
|
||||
InstrumentationManagerImpl im2 =
|
||||
@@ -166,7 +165,6 @@ public void testInstrumentBusWithBusProperties() {
|
||||
assertNotNull("Instrumentation Manager of cxf2 should not be null", im2);
|
||||
|
||||
assertFalse(im2.isEnabled());
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi", im2.getJMXServiceURL());
|
||||
|
||||
} finally {
|
||||
if (cxf1 != null) {
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java
|
||||
index e9f9308289a..6c458f3085b 100644
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java
|
||||
+++ b/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java
|
||||
@@ -64,12 +64,6 @@ public void tearDown() throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
- @Test
|
||||
- public void testRegisterMultipleBuses() throws Exception {
|
||||
- // classic external IM-bean
|
||||
- testRegisterMultipleBuses("managed-spring.xml");
|
||||
- }
|
||||
-
|
||||
@Test
|
||||
public void testRegisterMultipleBuses2() throws Exception {
|
||||
// integrated IM configuration in bus
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java
|
||||
index d516da39c06..20a7b091435 100644
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java
|
||||
+++ b/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java
|
||||
@@ -28,7 +28,6 @@
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.cxf.management.jmx.export.AnnotationTestInstrumentation;
|
||||
-import org.apache.cxf.testutil.common.TestUtil;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -38,17 +37,13 @@
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class JMXManagedComponentManagerTest {
|
||||
- private static final String PORT = TestUtil.getPortNumber(JMXManagedComponentManagerTest.class);
|
||||
private static final String NAME_ATTRIBUTE = "Name";
|
||||
private InstrumentationManagerImpl manager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
manager = new InstrumentationManagerImpl();
|
||||
- manager.setDaemon(false);
|
||||
- manager.setThreaded(true);
|
||||
manager.setEnabled(true);
|
||||
- manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
manager.init();
|
||||
//Wait for MBeanServer connector to be initialized on separate thread.
|
||||
Thread.sleep(2000);
|
||||
@@ -61,10 +56,6 @@ public void tearDown() throws Exception {
|
||||
|
||||
@Test
|
||||
public void testRegisterInstrumentation() throws Exception {
|
||||
- //manager.setDaemon(false);
|
||||
- //manager.setThreaded(false);
|
||||
- //manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi");
|
||||
- //manager.init();
|
||||
|
||||
AnnotationTestInstrumentation im = new AnnotationTestInstrumentation();
|
||||
ObjectName name = new ObjectName("org.apache.cxf:type=foo,name=bar");
|
||||
@@ -128,13 +119,7 @@ public void testBusLifecycleListener() throws Exception {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
|
||||
this.manager = new InstrumentationManagerImpl();
|
||||
- this.manager.setDaemon(false);
|
||||
- // Turn threading off so that we get the exception in this thread
|
||||
- // and the manager is set into a failed state if the connector
|
||||
- // cannot be created.
|
||||
- this.manager.setThreaded(false);
|
||||
this.manager.setEnabled(true);
|
||||
- this.manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
this.manager.setServer(server);
|
||||
this.manager.init();
|
||||
|
||||
@@ -161,13 +146,7 @@ public void testBusLifecycleListener() throws Exception {
|
||||
}
|
||||
|
||||
this.manager = new InstrumentationManagerImpl();
|
||||
- this.manager.setDaemon(false);
|
||||
- // Turn threading off so that we get the exception in this thread
|
||||
- // and the manager is set into a failed state if the connector
|
||||
- // cannot be created.
|
||||
- this.manager.setThreaded(false);
|
||||
this.manager.setEnabled(true);
|
||||
- this.manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
this.manager.setServer(server);
|
||||
this.manager.init();
|
||||
|
||||
@@ -183,4 +162,4 @@ private ObjectName registerStandardMBean(String name) throws Exception {
|
||||
this.manager.register(hw, oName);
|
||||
return oName;
|
||||
}
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java
|
||||
deleted file mode 100644
|
||||
index 468ec0cbfaf..00000000000
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java
|
||||
+++ /dev/null
|
||||
@@ -1,55 +0,0 @@
|
||||
-/**
|
||||
- * Licensed to the Apache Software Foundation (ASF) under one
|
||||
- * or more contributor license agreements. See the NOTICE file
|
||||
- * distributed with this work for additional information
|
||||
- * regarding copyright ownership. The ASF licenses this file
|
||||
- * to you 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 org.apache.cxf.management.jmx;
|
||||
-
|
||||
-import javax.management.remote.JMXServiceURL;
|
||||
-
|
||||
-import org.junit.Assert;
|
||||
-import org.junit.Test;
|
||||
-
|
||||
-
|
||||
-public class MBServerConnectorFactoryTest {
|
||||
-
|
||||
- @Test
|
||||
- public void testGetServerPort() throws Exception {
|
||||
- Assert.assertEquals(9914, MBServerConnectorFactory.getServerPort(
|
||||
- "service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"));
|
||||
-
|
||||
- Assert.assertEquals(10002, MBServerConnectorFactory.getServerPort(
|
||||
- "service:jmx:rmi://localhost:10002/jndi/rmi://localhost:10001/jmxrmi"));
|
||||
- }
|
||||
-
|
||||
- @Test
|
||||
- public void testGetRegistryPort() throws Exception {
|
||||
- Assert.assertEquals(9914, MBServerConnectorFactory.getRegistryPort(
|
||||
- "service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"));
|
||||
-
|
||||
- Assert.assertEquals(10001, MBServerConnectorFactory.getRegistryPort(
|
||||
- "service:jmx:rmi://localhost:10002/jndi/rmi://localhost:10001/jmxrmi"));
|
||||
- }
|
||||
-
|
||||
- @Test
|
||||
- public void testGetBindingName() throws Exception {
|
||||
- Assert.assertEquals("jmxrmi", MBServerConnectorFactory.getBindingName(
|
||||
- new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi")));
|
||||
-
|
||||
- Assert.assertEquals("cxf-jmxrmi", MBServerConnectorFactory.getBindingName(
|
||||
- new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9913/cxf-jmxrmi")));
|
||||
- }
|
||||
-}
|
||||
\ No newline at end of file
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorTest.java
|
||||
deleted file mode 100644
|
||||
index c01e10fc6f2..00000000000
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorTest.java
|
||||
+++ /dev/null
|
||||
@@ -1,57 +0,0 @@
|
||||
-/**
|
||||
- * Licensed to the Apache Software Foundation (ASF) under one
|
||||
- * or more contributor license agreements. See the NOTICE file
|
||||
- * distributed with this work for additional information
|
||||
- * regarding copyright ownership. The ASF licenses this file
|
||||
- * to you 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 org.apache.cxf.management.jmx;
|
||||
-
|
||||
-
|
||||
-
|
||||
-import javax.management.MBeanServer;
|
||||
-import javax.management.MBeanServerFactory;
|
||||
-
|
||||
-import org.apache.cxf.testutil.common.TestUtil;
|
||||
-
|
||||
-import org.junit.Test;
|
||||
-
|
||||
-import static org.junit.Assert.fail;
|
||||
-
|
||||
-
|
||||
-public class MBServerConnectorTest {
|
||||
- private static final String PORT = TestUtil.getPortNumber(MBServerConnectorTest.class);
|
||||
-
|
||||
- @Test
|
||||
- public void testMBServerConnector() {
|
||||
- MBServerConnectorFactory mcf;
|
||||
- MBeanServer mbs;
|
||||
- mbs = MBeanServerFactory.createMBeanServer("test");
|
||||
- mcf = MBServerConnectorFactory.getInstance();
|
||||
- mcf.setMBeanServer(mbs);
|
||||
- mcf.setThreaded(true);
|
||||
- mcf.setDaemon(true);
|
||||
- mcf.setServiceUrl("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
- try {
|
||||
- mcf.createConnector();
|
||||
- Thread.sleep(1000);
|
||||
- mcf.destroy();
|
||||
- } catch (Exception ex) {
|
||||
- ex.printStackTrace();
|
||||
- fail("Some Exception happened to MBServerConnectorTest");
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-}
|
||||
diff --git a/rt/management/src/test/resources/managed-spring.xml b/rt/management/src/test/resources/managed-spring.xml
|
||||
index 81808a54a5a..683c1b3ab32 100644
|
||||
--- a/rt/management/src/test/resources/managed-spring.xml
|
||||
+++ b/rt/management/src/test/resources/managed-spring.xml
|
||||
@@ -24,11 +24,7 @@
|
||||
xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
<cxf:bus id="CXF-Test-Bus" bus="cxf"/>
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
- <property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="threaded" value="false"/>
|
||||
- <property name="daemon" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
<cxf:workqueue name="default" highWaterMark="15" lowWaterMark="5"/>
|
||||
<cxf:workqueue name="test-wq" highWaterMark="10" lowWaterMark="2"/>
|
||||
diff --git a/rt/management/src/test/resources/managed-spring3.xml b/rt/management/src/test/resources/managed-spring3.xml
|
||||
index 83add997fe0..57009b7cf40 100644
|
||||
--- a/rt/management/src/test/resources/managed-spring3.xml
|
||||
+++ b/rt/management/src/test/resources/managed-spring3.xml
|
||||
@@ -26,9 +26,5 @@
|
||||
<!-- the bus setting at the end should not interfer with the other props -->
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="threaded" value="false"/>
|
||||
- <property name="daemon" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
- <property name="bus" ref="cxf"/>
|
||||
</bean>
|
||||
</beans>
|
||||
\ No newline at end of file
|
||||
diff --git a/rt/management/src/test/resources/no-connector-spring.xml b/rt/management/src/test/resources/no-connector-spring.xml
|
||||
index f6c197d9a2c..565d92dffe0 100644
|
||||
--- a/rt/management/src/test/resources/no-connector-spring.xml
|
||||
+++ b/rt/management/src/test/resources/no-connector-spring.xml
|
||||
@@ -24,6 +24,5 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="createMBServerConnectorFactory" value="false"/>
|
||||
</bean>
|
||||
</beans>
|
||||
\ No newline at end of file
|
||||
diff --git a/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml b/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml
|
||||
index 8e01539b360..7571a48693d 100644
|
||||
--- a/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml
|
||||
+++ b/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml
|
||||
@@ -26,9 +26,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="threaded" value="false"/>
|
||||
- <property name="daemon" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
<cxf:bus>
|
||||
<cxf:features>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java
|
||||
index dbde562570a..a40c61d394c 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java
|
||||
@@ -98,8 +98,6 @@ public void testManagedSpringBus() throws Exception {
|
||||
assertNotNull(im);
|
||||
|
||||
InstrumentationManagerImpl imi = (InstrumentationManagerImpl)im;
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi",
|
||||
- imi.getJMXServiceURL());
|
||||
assertFalse(imi.isEnabled());
|
||||
assertNull(imi.getMBeanServer());
|
||||
|
||||
@@ -127,8 +125,6 @@ private void doManagedBusTest(Bus bus, String expect, String reject, int port) t
|
||||
InstrumentationManager im = bus.getExtension(InstrumentationManager.class);
|
||||
assertNotNull(im);
|
||||
InstrumentationManagerImpl imi = (InstrumentationManagerImpl)im;
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:" + port + "/jmxrmi",
|
||||
- imi.getJMXServiceURL());
|
||||
assertTrue(imi.isEnabled());
|
||||
assertNotNull(imi.getMBeanServer());
|
||||
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml
|
||||
index e5cc90f9a17..b3d516022d9 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.CountersClientServerTest.1}/jmxrmi"/>
|
||||
</bean>
|
||||
<bean id="org.apache.cxf.management.counters.CounterRepository" class="org.apache.cxf.management.counters.CounterRepository">
|
||||
<property name="bus" ref="cxf"/>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml
|
||||
index 7304a399d39..fed391b4a60 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.ManagedBusTest.1}/jmxrmi"/>
|
||||
</bean>
|
||||
<bean id="wq" class="org.apache.cxf.workqueue.AutomaticWorkQueueImpl">
|
||||
<property name="name" value="testQueue"/>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml
|
||||
index 4beb120a457..fed391b4a60 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.ManagedClientServerTest.1}/jmxrmi"/>
|
||||
</bean>
|
||||
<bean id="wq" class="org.apache.cxf.workqueue.AutomaticWorkQueueImpl">
|
||||
<property name="name" value="testQueue"/>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml
|
||||
index 118abfe7978..9219b56bcf3 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.ManagedBusTest.3}/jmxrmi"/>
|
||||
<property name="persistentBusId" value="cxf:managed,bus=test"/>
|
||||
</bean>
|
||||
<bean id="wq" class="org.apache.cxf.workqueue.AutomaticWorkQueueImpl">
|
||||
diff --git a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml
|
||||
index c0cd5b2700a..514038f02b8 100644
|
||||
--- a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml
|
||||
+++ b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml
|
||||
@@ -43,7 +43,5 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="createMBServerConnectorFactory" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
-</beans>
|
||||
\ No newline at end of file
|
||||
+</beans>
|
||||
diff --git a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml
|
||||
index 823d8f0622e..1ee90cfbae4 100644
|
||||
--- a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml
|
||||
+++ b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml
|
||||
@@ -43,6 +43,5 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
-</beans>
|
||||
\ No newline at end of file
|
||||
+</beans>
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
diff -r fcd3ed3394f6 -r 135bdcb88b8d coders/wpg.c
|
||||
--- a/coders/wpg.c Sun Nov 05 01:11:09 2017 +0100
|
||||
+++ b/coders/wpg.c Sun Nov 05 01:35:28 2017 +0100
|
||||
@@ -340,12 +340,15 @@
|
||||
|
||||
|
||||
if(RetVal==MagickFail)
|
||||
+ {
|
||||
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"ImportImagePixelArea failed for row: %ld, bpp: %d", y, bpp);
|
||||
+ return MagickFail;
|
||||
+ }
|
||||
|
||||
- if (!SyncImagePixels(image))
|
||||
+ if(!SyncImagePixels(image))
|
||||
{
|
||||
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"SyncImagePixels failed for row: %ld, bpp: %d", y, bpp);
|
||||
- RetVal = MagickFail;
|
||||
+ return MagickFail;
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
Index: src/java/test/org/apache/zookeeper/test/ACLTest.java
|
||||
===================================================================
|
||||
--- src/java/test/org/apache/zookeeper/test/ACLTest.java (revision 1510080)
|
||||
+++ src/java/test/org/apache/zookeeper/test/ACLTest.java (working copy)
|
||||
@@ -28,6 +28,7 @@
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.zookeeper.CreateMode;
|
||||
+import org.apache.zookeeper.KeeperException;
|
||||
import org.apache.zookeeper.PortAssignment;
|
||||
import org.apache.zookeeper.WatchedEvent;
|
||||
import org.apache.zookeeper.Watcher;
|
||||
@@ -35,8 +36,10 @@
|
||||
import org.apache.zookeeper.ZooKeeper;
|
||||
import org.apache.zookeeper.Watcher.Event.KeeperState;
|
||||
import org.apache.zookeeper.ZooDefs.Ids;
|
||||
+import org.apache.zookeeper.ZooDefs.Perms;
|
||||
import org.apache.zookeeper.data.ACL;
|
||||
import org.apache.zookeeper.data.Id;
|
||||
+import org.apache.zookeeper.data.Stat;
|
||||
import org.apache.zookeeper.server.ServerCnxnFactory;
|
||||
import org.apache.zookeeper.server.SyncRequestProcessor;
|
||||
import org.apache.zookeeper.server.ZooKeeperServer;
|
||||
@@ -77,6 +80,48 @@
|
||||
ClientBase.CONNECTION_TIMEOUT));
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Verify that getAcl should fail when there is not
|
||||
+ * read permission to that node
|
||||
+ */
|
||||
+ @Test
|
||||
+ public void testAclReadPermission() throws Exception {
|
||||
+ File tmpDir = ClientBase.createTmpDir();
|
||||
+ ClientBase.setupTestEnv();
|
||||
+ ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
|
||||
+ SyncRequestProcessor.setSnapCount(1000);
|
||||
+ final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
|
||||
+ ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
|
||||
+ f.startup(zks);
|
||||
+ ZooKeeper zk;
|
||||
+ String path = "/node1";
|
||||
+ boolean readPermLimitWorks = false;
|
||||
+ try {
|
||||
+ LOG.info("starting up the zookeeper server .. waiting");
|
||||
+ Assert.assertTrue("waiting for server being up",
|
||||
+ ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
|
||||
+ zk = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, this);
|
||||
+ Id id = new Id("ip", "127.0.0.1");
|
||||
+ ArrayList<ACL> acl = new ArrayList<ACL>(); // Not set read permission
|
||||
+ acl.add(new ACL(Perms.CREATE, id));
|
||||
+ acl.add(new ACL(Perms.DELETE, id));
|
||||
+ acl.add(new ACL(Perms.WRITE, id));
|
||||
+ acl.add(new ACL(Perms.ADMIN, id));
|
||||
+ zk.create(path, path.getBytes(), acl, CreateMode.PERSISTENT);
|
||||
+ Stat stat = new Stat();
|
||||
+ zk.getACL(path, stat); // Should cause exception without read permission
|
||||
+ } catch (KeeperException.NoAuthException e) {
|
||||
+ readPermLimitWorks = true;
|
||||
+ } finally {
|
||||
+ f.shutdown();
|
||||
+ Assert.assertTrue("waiting for server down",
|
||||
+ ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT));
|
||||
+ }
|
||||
+ if (!readPermLimitWorks) {
|
||||
+ Assert.fail("Should not reach here as ACL has no read permission");
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/**
|
||||
* Verify that acl optimization of storing just
|
||||
Index: src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java
|
||||
===================================================================
|
||||
--- src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java (revision 1510080)
|
||||
+++ src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java (working copy)
|
||||
@@ -324,6 +324,17 @@
|
||||
GetACLRequest getACLRequest = new GetACLRequest();
|
||||
ByteBufferInputStream.byteBuffer2Record(request.request,
|
||||
getACLRequest);
|
||||
+ DataNode n = zks.getZKDatabase().getNode(getACLRequest.getPath());
|
||||
+ if (n == null) {
|
||||
+ throw new KeeperException.NoNodeException();
|
||||
+ }
|
||||
+ Long aclL;
|
||||
+ synchronized(n) {
|
||||
+ aclL = n.acl;
|
||||
+ }
|
||||
+ PrepRequestProcessor.checkACL(zks, zks.getZKDatabase().convertLong(aclL),
|
||||
+ ZooDefs.Perms.READ,
|
||||
+ request.authInfo);
|
||||
Stat stat = new Stat();
|
||||
List<ACL> acl =
|
||||
zks.getZKDatabase().getACL(getACLRequest.getPath(), stat);
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a.txt
|
||||
+++ a1.txt
|
||||
@@ -8,7 +8,7 @@
|
||||
<Setting>
|
||||
<Setting a>
|
||||
<setting b>
|
||||
- <value>23</value>
|
||||
+ <value>24</value>
|
||||
</setting b>
|
||||
<setting c>
|
||||
<value>1</value>
|
||||
@@ -0,0 +1,4 @@
|
||||
diff --git a/some-image.png b/some-image.png
|
||||
new file mode 100644
|
||||
index 0000000..bc3b5b4
|
||||
Binary files /dev/null and b/some-image.png differ
|
||||
@@ -0,0 +1,4 @@
|
||||
diff --git a/some-image.png b/some-image.png
|
||||
deleted file mode 100644
|
||||
index 0e68078..0000000
|
||||
Binary files a/some-image.png and /dev/null differ
|
||||
@@ -0,0 +1,3 @@
|
||||
diff --git a/some-image.png b/some-image.png
|
||||
index bc3b5b4..0e68078 100644
|
||||
Binary files a/some-image.png and b/some-image.png differ
|
||||
@@ -0,0 +1,3 @@
|
||||
diff --git a/some-image.png b/some-image.png
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
@@ -0,0 +1,26 @@
|
||||
diff --git src://modules/configuration/config/web/pcf/account/AccountContactCV.pcf dst://modules/configuration/config/web/pcf/account/AccountContactCV.default.pcf
|
||||
similarity index 99%
|
||||
copy from modules/configuration/config/web/pcf/account/AccountContactCV.pcf
|
||||
copy to modules/configuration/config/web/pcf/account/AccountContactCV.default.pcf
|
||||
index 13efef5778..1a08b0befc 100644
|
||||
--- src://modules/configuration/config/web/pcf/account/AccountContactCV.pcf
|
||||
+++ dst://modules/configuration/config/web/pcf/account/AccountContactCV.default.pcf
|
||||
@@ -1,16 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<PCF
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../../../pcf.xsd">
|
||||
<CardViewPanel
|
||||
- id="AccountContactCV">
|
||||
+ id="AccountContactCV"
|
||||
+ mode="default">
|
||||
<Require
|
||||
name="acctContact"
|
||||
type="AccountContact"/>
|
||||
<Require
|
||||
name="showAddressTools"
|
||||
type="boolean"/>
|
||||
<Require
|
||||
name="showRolesTab"
|
||||
type="boolean"/>
|
||||
<Variable
|
||||
@@ -1,7 +1,7 @@
|
||||
handlers=java.util.logging.ConsoleHandler
|
||||
|
||||
.level=INFO
|
||||
com.github.difflib.unifieddiff.level=FINE
|
||||
com.github.difflib.unifieddiff.level=INFO
|
||||
|
||||
java.util.logging.ConsoleHandler.level=INFO
|
||||
#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
//According to the original text, an html will be generated by comparing the text
|
||||
public class generateDiffHtmlTest {
|
||||
/**
|
||||
* Here's a simple example of getting a nice html page based on the original text and the contrasted text,Read n1.txt and n2.txt of D disk, and finally generate an html file
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public static void generateOriginalAndDiffDemo(){
|
||||
List<String> origLines = getFileContent("D:\\n1.txt");
|
||||
List<String> revLines =getFileContent("D:\\n2.txt");
|
||||
List<String> originalAndDiff =UnifiedDiffUtils.generateOriginalAndDiff(origLines, revLines);
|
||||
//System.out.println(originalAndDiff.size());
|
||||
generateDiffHtml(originalAndDiff,"D:\\diff.html");
|
||||
}
|
||||
|
||||
/**
|
||||
* get file content
|
||||
* @param filePath file path
|
||||
*/
|
||||
public static List<String> getFileContent(String filePath) {
|
||||
//origin
|
||||
List<String> fileContent =null;
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
fileContent = Files.readAllLines(file.toPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* The html file is generated by the difference diff between the two files, and the detailed content of the file comparison can be seen by opening the html file
|
||||
*
|
||||
*/
|
||||
public static void generateDiffHtml(List<String> diffString, String htmlPath) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String line : diffString) {
|
||||
builder.append(line);
|
||||
builder.append("\n");
|
||||
}
|
||||
String githubCss = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.1/styles/github.min.css";
|
||||
String diff2htmlCss = "https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css";
|
||||
String diff2htmlJs = "https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js";
|
||||
|
||||
String template = "<!DOCTYPE html>\n" +
|
||||
"<html lang=\"en-us\">\n" +
|
||||
" <head>\n" +
|
||||
" <meta charset=\"utf-8\" />\n" +
|
||||
" <link rel=\"stylesheet\" href=\"" + githubCss + "\" />\n" +
|
||||
" <link rel=\"stylesheet\" type=\"text/css\" href=\"" + diff2htmlCss + "\" />\n" +
|
||||
" <script type=\"text/javascript\" src=\"" + diff2htmlJs + "\"></script>\n" +
|
||||
" </head>\n" +
|
||||
" <script>\n" +
|
||||
" const diffString = `\n" +
|
||||
"temp\n" +
|
||||
"`;\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
" document.addEventListener('DOMContentLoaded', function () {\n" +
|
||||
" var targetElement = document.getElementById('myDiffElement');\n" +
|
||||
" var configuration = {\n" +
|
||||
" drawFileList: true,\n" +
|
||||
" fileListToggle: true,\n" +
|
||||
" fileListStartVisible: true,\n" +
|
||||
" fileContentToggle: true,\n" +
|
||||
" matching: 'lines',\n" +
|
||||
" outputFormat: 'side-by-side',\n" +
|
||||
" synchronisedScroll: true,\n" +
|
||||
" highlight: true,\n" +
|
||||
" renderNothingWhenEmpty: true,\n" +
|
||||
" };\n" +
|
||||
" var diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);\n" +
|
||||
" diff2htmlUi.draw();\n" +
|
||||
" diff2htmlUi.highlightCode();\n" +
|
||||
" });\n" +
|
||||
" </script>\n" +
|
||||
" <body>\n" +
|
||||
" <div id=\"myDiffElement\"></div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
template = template.replace("temp", builder.toString());
|
||||
FileWriter fileWriter = null;
|
||||
try {
|
||||
fileWriter = new FileWriter(htmlPath);
|
||||
BufferedWriter buf = new BufferedWriter(fileWriter);
|
||||
buf.write(template);
|
||||
buf.close();
|
||||
fileWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
114
java-diff-utils/src/test/resources/mocks/issue_170_revised.txt
Normal file
114
java-diff-utils/src/test/resources/mocks/issue_170_revised.txt
Normal file
@@ -0,0 +1,114 @@
|
||||
package com.github.difflib.examples;
|
||||
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
|
||||
// According to the original text, an html will be generated by comparing the text.
|
||||
public class generateDiffHtmlTest {
|
||||
|
||||
/**
|
||||
* Here's a simple example of getting a nice html page based on the original text and the contrasted text,
|
||||
* Read n1.txt and n2.txt of D disk, and finally generate an html file
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public static void generateOriginalAndDiffDemo(){
|
||||
List<String> origLines = getFileContent("D:\\n1.txt");
|
||||
List<String> revLines = getFileContent("D:\\n2.txt");
|
||||
List<String> originalAndDiff = UnifiedDiffUtils.generateOriginalAndDiff(origLines, revLines);
|
||||
|
||||
//generateDiffHtml
|
||||
generateDiffHtml(originalAndDiff,"D:\\diff.html");
|
||||
}
|
||||
|
||||
/**
|
||||
* get file content
|
||||
*
|
||||
* @param filePath file path
|
||||
*/
|
||||
public static List<String> getFileContent(String filePath) {
|
||||
//原始文件
|
||||
List<String> fileContent = null;
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
fileContent = Files.readAllLines(file.toPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* The html file is generated by the difference diff between the two files,
|
||||
* and the detailed content of the file comparison can be seen by opening the html file
|
||||
*
|
||||
* @param diffString The comparison result obtained by calling the above diffString method
|
||||
* @param htmlPath Generated html path,e.g:/user/var/mbos/ent/21231/diff.html
|
||||
*/
|
||||
public static void generateDiffHtml(List<String> diffString, String htmlPath) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String line : diffString) {
|
||||
builder.append(line);
|
||||
builder.append("\n");
|
||||
}
|
||||
String githubCss = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.1/styles/github.min.css";
|
||||
String diff2htmlCss = "https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css";
|
||||
String diff2htmlJs = "https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js";
|
||||
|
||||
String template = "<!DOCTYPE html>\n" +
|
||||
"<html lang=\"en-us\">\n" +
|
||||
" <head>\n" +
|
||||
" <meta charset=\"utf-8\" />\n" +
|
||||
" <link rel=\"stylesheet\" href=\"" + githubCss + "\" />\n" +
|
||||
" <link rel=\"stylesheet\" type=\"text/css\" href=\"" + diff2htmlCss + "\" />\n" +
|
||||
" <script type=\"text/javascript\" src=\"" + diff2htmlJs + "\"></script>\n" +
|
||||
" </head>\n" +
|
||||
" <script>\n" +
|
||||
" const diffString = `\n" +
|
||||
"temp\n" +
|
||||
"`;\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
" document.addEventListener('DOMContentLoaded', function () {\n" +
|
||||
" var targetElement = document.getElementById('myDiffElement');\n" +
|
||||
" var configuration = {\n" +
|
||||
" drawFileList: true,\n" +
|
||||
" fileListToggle: true,\n" +
|
||||
" fileListStartVisible: true,\n" +
|
||||
" fileContentToggle: true,\n" +
|
||||
" matching: 'lines',\n" +
|
||||
" outputFormat: 'side-by-side',\n" +
|
||||
" synchronisedScroll: true,\n" +
|
||||
" highlight: true,\n" +
|
||||
" renderNothingWhenEmpty: true,\n" +
|
||||
" };\n" +
|
||||
" var diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);\n" +
|
||||
" diff2htmlUi.draw();\n" +
|
||||
" diff2htmlUi.highlightCode();\n" +
|
||||
" });\n" +
|
||||
" </script>\n" +
|
||||
" <body>\n" +
|
||||
" <div id=\"myDiffElement\"></div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
template = template.replace("temp", builder.toString());
|
||||
FileWriter fileWriter = null;
|
||||
try {
|
||||
fileWriter = new FileWriter(htmlPath);
|
||||
BufferedWriter buf = new BufferedWriter(fileWriter);
|
||||
buf.write(template);
|
||||
buf.close();
|
||||
fileWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
pom.xml
17
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.15</version>
|
||||
<name>java-diff-utils-parent</name>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
@@ -29,7 +29,7 @@
|
||||
<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.10</tag>
|
||||
<tag>java-diff-utils-parent-4.15</tag>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
<system>GitHub Issues</system>
|
||||
@@ -65,13 +65,13 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.7.1</version>
|
||||
<version>5.11.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.19.0</version>
|
||||
<version>3.26.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -86,12 +86,13 @@
|
||||
<localCheckout>true</localCheckout>
|
||||
<pushChanges>false</pushChanges>
|
||||
<mavenExecutorId>forked-path</mavenExecutorId>
|
||||
<releaseProfiles>sign-release-artifacts</releaseProfiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.5.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
@@ -122,7 +123,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>verify-style</id>
|
||||
@@ -176,7 +177,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M4</version>
|
||||
<version>3.5.2</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/LR*.java</exclude>
|
||||
@@ -199,7 +200,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
|
||||
Reference in New Issue
Block a user