утренние изменения

удаление эталона и роль студента
This commit is contained in:
2025-03-26 16:12:00 +03:00
parent 1ae4d1980a
commit 19afec4d25
62 changed files with 576 additions and 1098 deletions

63
.idea/workspace.xml generated
View File

@@ -9,13 +9,66 @@
<list default="true" id="e42177c3-2328-4b27-8a01-35779b2beb99" name="Default Changelist" comment=""> <list default="true" id="e42177c3-2328-4b27-8a01-35779b2beb99" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/properties" beforeDir="false" afterPath="$PROJECT_DIR$/properties" afterDir="false" /> <change beforePath="$PROJECT_DIR$/properties" beforeDir="false" afterPath="$PROJECT_DIR$/properties" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/ComponentsServer/UserAccount/AccountRole.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/ComponentsServer/UserAccount/AccountRole.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerEnvironment/Json/EnvironmentJson.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerEnvironment/Json/EnvironmentJson.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/ComponentsServer/UserAccount/UI/UserAccountFields.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/ComponentsServer/UserAccount/UI/UserAccountFields.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerOption/Json/OptionJson.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerOption/Json/OptionJson.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Constants.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Constants.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerOption/Json/OptionsJson.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerOption/Json/OptionsJson.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerOption/Json/OptionsSetJson.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/GlobalData/CompilerOption/Json/OptionsSetJson.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/MainModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/MainModule.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/MainModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/MainModule.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Visual/Interface/MainWindow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Visual/Interface/MainWindow.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/Passes/All/CompareSapforPackageToEthalon.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Passes/All/CompareSapforPackageToEthalon.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Passes/All/DropSapforConfigurationEthalon.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Passes/All/DropSapforConfigurationEthalon.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Passes/All/TestPass.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Passes/All/TestPass.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Passes/PassCode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Passes/PassCode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/ServerObjectsCache/DVMSettingsCache.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/ServerObjectsCache/DVMSettingsCache.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/Common/TestsDatabase.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/Common/TestsDatabase.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOption/DVMCompilationOption.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOption/DVMCompilationOption.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOption/DVMCompilationOptionsDBTable.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOption/DVMCompilationOptionsDBTable.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOptionsSet/DVMCompilationOptionsSet.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOptionsSet/DVMCompilationOptionsSet.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOptionsSet/DVMCompilationOptionsSetsDBTable.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMCompilationOptionsSet/DVMCompilationOptionsSetsDBTable.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMEnvironment/DVMEnvironment.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMEnvironment/DVMEnvironment.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMEnvironment/DVMEnvironmentsDBTable.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMEnvironment/DVMEnvironmentsDBTable.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMEnvironmentsSet/DVMEnvironmentsSet.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMEnvironmentsSet/DVMEnvironmentsSet.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMPackage/DVMPackage.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMPackage/DVMPackage.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMPackageConfiguration/DVMPackageConfiguration.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMPackageConfiguration/DVMPackageConfiguration.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMSettings/DVMSettings.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMSettings/DVMSettings.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMSettings/UI/DVMSettingsFields.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/DVM/DVMSettings/UI/DVMSettingsFields.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforConfiguration/UI/SapforConfigurationFields.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforConfiguration/UI/SapforConfigurationFields.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforConfigurationSettings/SapforConfigurationSettings.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforConfigurationSettings/SapforConfigurationSettings.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforPackage/UI/SapforPackagesForm.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforPackage/UI/SapforPackagesForm.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforPackageConfiguration/SapforPackageConfiguration.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/TestingSystem/SAPFOR/SapforPackageConfiguration/SapforPackageConfiguration.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Visual/MainUI.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Visual/MainUI.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/Visual/MainUI.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Visual/MainUI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Visual/Windows/MainForm.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Visual/Windows/MainForm.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/_VisualDVM/Visual/Menus/MainMenuBar/VisualiserSettingsMenu/VersionsComparisonMenu.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Visual/Menus/MainMenuBar/VisualiserSettingsMenu/VersionsComparisonMenu.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/_VisualDVM/Visual/Windows/ComparisonForm.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/_VisualDVM/Visual/Windows/ComparisonForm.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/DiffUtils.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/DiffUtils.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/UnifiedDiffUtils.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/UnifiedDiffUtils.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/Change.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/Change.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/DiffAlgorithmFactory.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/DiffAlgorithmFactory.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/DiffAlgorithmI.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/DiffAlgorithmI.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/DiffAlgorithmListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/DiffAlgorithmListener.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/myers/MyersDiff.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/myers/MyersDiff.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/myers/MyersDiffWithLinearSpace.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/myers/MyersDiffWithLinearSpace.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/algorithm/myers/PathNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/algorithm/myers/PathNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/AbstractDelta.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/AbstractDelta.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/ChangeDelta.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/ChangeDelta.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/Chunk.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/Chunk.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/ConflictOutput.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/ConflictOutput.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/DeleteDelta.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/DeleteDelta.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/DeltaType.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/DeltaType.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/DiffException.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/DiffException.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/EqualDelta.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/EqualDelta.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/InsertDelta.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/InsertDelta.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/Patch.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/Patch.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/PatchFailedException.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/PatchFailedException.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/patch/VerifyChunk.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/patch/VerifyChunk.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/text/DiffRow.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/text/DiffRow.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/text/DiffRowGenerator.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/text/DiffRowGenerator.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/text/StringUtils.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/text/StringUtils.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/text/deltamerge/DeltaMergeUtils.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/text/deltamerge/DeltaMergeUtils.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/text/deltamerge/InlineDeltaMergeInfo.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/text/deltamerge/InlineDeltaMergeInfo.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiff.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiff.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffFile.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffFile.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffParserException.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffParserException.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffReader.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffReader.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffWriter.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/com/github/difflib/unifieddiff/UnifiedDiffWriter.java" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />

View File

@@ -4,7 +4,7 @@
"ServerUserPassword": "mprit_2011", "ServerUserPassword": "mprit_2011",
"OfferRegistrationOnStart": true, "OfferRegistrationOnStart": true,
"Workspace": "E:\\Tests", "Workspace": "E:\\Tests",
"ProjectsSearchDirectory": "E:\\BUG", "ProjectsSearchDirectory": "E:\\Tests\\Downloads\\bugreport_1732220374\\zebra\\v1",
"DocumentsDirectory": "C:\\Users\\misha\\Documents\\_testing_system", "DocumentsDirectory": "C:\\Users\\misha\\Documents\\_testing_system",
"VisualiserPath": "C:\\Users\\misha\\Downloads", "VisualiserPath": "C:\\Users\\misha\\Downloads",
"Sapfor_FPath": "E:\\_sapfor_x64\\Components\\Sapfor_F", "Sapfor_FPath": "E:\\_sapfor_x64\\Components\\Sapfor_F",

View File

@@ -1,8 +1,6 @@
package _VisualDVM.GlobalData.CompilerOption.Json; package _VisualDVM.GlobalData.CompilerOption.Json;
import _VisualDVM.GlobalData.CompilerOption.CompilerOption; import _VisualDVM.GlobalData.CompilerOption.CompilerOption;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import java.io.Serializable;
public class OptionJson { public class OptionJson {
@Expose @Expose
public String name; //в том числе и с разделителем если есть. поиск по startswith public String name; //в том числе и с разделителем если есть. поиск по startswith

View File

@@ -2,7 +2,6 @@ package _VisualDVM.GlobalData.CompilerOption.Json;
import Common.Utils.Utils_; import Common.Utils.Utils_;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
public class OptionsJson { public class OptionsJson {

View File

@@ -1,7 +1,6 @@
package _VisualDVM.GlobalData.CompilerOption.Json; package _VisualDVM.GlobalData.CompilerOption.Json;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
public class OptionsSetJson { public class OptionsSetJson {

View File

@@ -1,12 +1,9 @@
package _VisualDVM.Passes.All; package _VisualDVM.Passes.All;
import Common.CommonConstants; import Common.CommonConstants;
import Common.Passes.Pass;
import Common.Utils.Utils_; import Common.Utils.Utils_;
import Common.Visual.UI; import Common.Visual.UI;
import _VisualDVM.Global; import _VisualDVM.Global;
import _VisualDVM.TestingSystem.SAPFOR.SapforPackage.SapforPackage; import _VisualDVM.TestingSystem.SAPFOR.SapforPackage.SapforPackage;
import java.util.Vector;
public class CompareSapforPackageToEthalon extends CompareSapforPackages { public class CompareSapforPackageToEthalon extends CompareSapforPackages {
@Override @Override
protected boolean canStart(Object... args) throws Exception { protected boolean canStart(Object... args) throws Exception {

View File

@@ -1,6 +1,5 @@
package _VisualDVM.Passes.All; package _VisualDVM.Passes.All;
import Common.CommonConstants; import Common.CommonConstants;
import _VisualDVM.Global;
public class DropSapforConfigurationEthalon extends EditSapforConfiguration { public class DropSapforConfigurationEthalon extends EditSapforConfiguration {
@Override @Override
public String getIconPath() { public String getIconPath() {

View File

@@ -45,7 +45,6 @@ public class TestPass extends Pass {
@Override @Override
protected void body() throws Exception { protected void body() throws Exception {
List<Integer> numbers = new Vector_<>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); List<Integer> numbers = new Vector_<>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Use parallelStream() to create a parallel stream // Use parallelStream() to create a parallel stream
ForkJoinPool commonPool = ForkJoinPool.commonPool(); ForkJoinPool commonPool = ForkJoinPool.commonPool();
commonPool.submit(() -> commonPool.submit(() ->
@@ -57,7 +56,6 @@ public class TestPass extends Pass {
).join(); ).join();
System.out.println("DONE"); System.out.println("DONE");
//---- //----
DiffRowGenerator generator = DiffRowGenerator.create() DiffRowGenerator generator = DiffRowGenerator.create()
.showInlineDiffs(true) .showInlineDiffs(true)
.inlineDiffByWord(true) .inlineDiffByWord(true)
@@ -67,7 +65,6 @@ public class TestPass extends Pass {
List<DiffRow> rows = generator.generateDiffRows( 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 senctence.", "This is the second line.", "And here is the finish."),
Arrays.asList("This is a test for diffutils.", "This is the second line.")); Arrays.asList("This is a test for diffutils.", "This is the second line."));
System.out.println("|original|new|"); System.out.println("|original|new|");
System.out.println("|--------|---|"); System.out.println("|--------|---|");
for (DiffRow row : rows) { for (DiffRow row : rows) {

View File

@@ -361,8 +361,7 @@ public enum PassCode implements PassCode_ {
ComponentsServerBackUp, ComponentsServerBackUp,
TestingServerBackUp, TestingServerBackUp,
CompareDVMRunTaskToEthalon, CompareDVMRunTaskToEthalon,
DropSapforConfigurationEthalon DropSapforConfigurationEthalon;
;
//-- //--
@Override @Override
public String getDescription() { public String getDescription() {

View File

@@ -5,7 +5,6 @@ import _VisualDVM.TestingSystem.DVM.DVMCompilationOptionsSet.DVMCompilationOptio
import _VisualDVM.TestingSystem.DVM.DVMEnvironment.DVMEnvironment; import _VisualDVM.TestingSystem.DVM.DVMEnvironment.DVMEnvironment;
import _VisualDVM.TestingSystem.DVM.DVMEnvironmentsSet.DVMEnvironmentsSet; import _VisualDVM.TestingSystem.DVM.DVMEnvironmentsSet.DVMEnvironmentsSet;
import _VisualDVM.TestingSystem.DVM.DVMSettings.DVMSettings; import _VisualDVM.TestingSystem.DVM.DVMSettings.DVMSettings;
import javafx.util.Pair;
import java.util.Vector; import java.util.Vector;
public class DVMSettingsCache extends VisualCache { public class DVMSettingsCache extends VisualCache {

View File

@@ -105,6 +105,18 @@ public class TestsDatabase extends SQLiteDatabase {
public TestsDatabase() { public TestsDatabase() {
super(Paths.get(System.getProperty("user.dir"), "Data", Constants.tests_db_name + ".sqlite").toFile()); super(Paths.get(System.getProperty("user.dir"), "Data", Constants.tests_db_name + ".sqlite").toFile());
} }
public static String printOptionsLine(Vector<DVMCompilationOption> options) {
Vector<String> res = new Vector<>();
for (DVMCompilationOption option : options)
res.add(option.print());
return String.join(" ", res);
}
public static String printEnvironmentsLine(Vector<DVMEnvironment> environments) {
Vector<String> res = new Vector<>();
for (DVMEnvironment environment : environments)
res.add(environment.print());
return String.join(" ", res);
}
@Override @Override
protected void initAllTables() throws Exception { protected void initAllTables() throws Exception {
addTable(groups = new GroupsDBTable()); addTable(groups = new GroupsDBTable());
@@ -702,18 +714,6 @@ public class TestsDatabase extends SQLiteDatabase {
Commit(); Commit();
*/ */
} }
public static String printOptionsLine(Vector<DVMCompilationOption> options) {
Vector<String> res = new Vector<>();
for (DVMCompilationOption option : options)
res.add(option.print());
return String.join(" ", res);
}
public static String printEnvironmentsLine(Vector<DVMEnvironment> environments) {
Vector<String> res = new Vector<>();
for (DVMEnvironment environment : environments)
res.add(environment.print());
return String.join(" ", res);
}
public Vector<Pair<String, String>> getTasksParameters(DVMSettings dvmSettings_in) { public Vector<Pair<String, String>> getTasksParameters(DVMSettings dvmSettings_in) {
//уравниваем количество наборов опций и окружений и сопоставляем 1 к 1 //уравниваем количество наборов опций и окружений и сопоставляем 1 к 1
Vector<Pair<String, String>> res = new Vector<>(); Vector<Pair<String, String>> res = new Vector<>();

View File

@@ -11,6 +11,8 @@ public class DVMCompilationOption extends iDBObject {
name = name_in; name = name_in;
value = value_in; value = value_in;
} }
public DVMCompilationOption() {
}
@Override @Override
public void SynchronizeFields(DBObject src) { public void SynchronizeFields(DBObject src) {
super.SynchronizeFields(src); super.SynchronizeFields(src);
@@ -19,7 +21,6 @@ public class DVMCompilationOption extends iDBObject {
value = src_.value; value = src_.value;
dvmcompilationoptionsset_id = src_.dvmcompilationoptionsset_id; dvmcompilationoptionsset_id = src_.dvmcompilationoptionsset_id;
} }
public DVMCompilationOption(){}
public String print() { public String print() {
return name + (value.contains(" ") ? Utils_.DQuotes(value) : value); return name + (value.contains(" ") ? Utils_.DQuotes(value) : value);
} }

View File

@@ -1,13 +1,5 @@
package _VisualDVM.TestingSystem.DVM.DVMCompilationOption; package _VisualDVM.TestingSystem.DVM.DVMCompilationOption;
import Common.Database.Objects.DBObject;
import Common.Database.Tables.FKBehaviour;
import Common.Database.Tables.FKCurrentObjectBehaviuor;
import Common.Database.Tables.FKDataBehaviour;
import Common.Database.Tables.iDBTable; import Common.Database.Tables.iDBTable;
import _VisualDVM.TestingSystem.DVM.DVMCompilationOptionsSet.DVMCompilationOptionsSet;
import _VisualDVM.TestingSystem.DVM.DVMConfigurationSettings.DVMConfigurationSettings;
import java.util.LinkedHashMap;
public class DVMCompilationOptionsDBTable extends iDBTable<DVMCompilationOption> { public class DVMCompilationOptionsDBTable extends iDBTable<DVMCompilationOption> {
public DVMCompilationOptionsDBTable() { public DVMCompilationOptionsDBTable() {
super(DVMCompilationOption.class); super(DVMCompilationOption.class);

View File

@@ -11,15 +11,15 @@ public class DVMCompilationOptionsSet extends iDBObject {
public int dvmsettings_id = CommonConstants.Nan; public int dvmsettings_id = CommonConstants.Nan;
@Description("IGNORE") @Description("IGNORE")
public Vector<DVMCompilationOption> options = null; public Vector<DVMCompilationOption> options = null;
public DVMCompilationOptionsSet() {
}
public DVMCompilationOptionsSet(DVMSettings settings_in) {
dvmsettings_id = settings_in.id;
}
@Override @Override
public void SynchronizeFields(DBObject src) { public void SynchronizeFields(DBObject src) {
super.SynchronizeFields(src); super.SynchronizeFields(src);
DVMCompilationOptionsSet src_ = (DVMCompilationOptionsSet) src; DVMCompilationOptionsSet src_ = (DVMCompilationOptionsSet) src;
dvmsettings_id = src_.dvmsettings_id; dvmsettings_id = src_.dvmsettings_id;
} }
public DVMCompilationOptionsSet() {
}
public DVMCompilationOptionsSet(DVMSettings settings_in) {
dvmsettings_id = settings_in.id;
}
} }

View File

@@ -4,10 +4,8 @@ import Common.Database.Tables.FKBehaviour;
import Common.Database.Tables.FKCurrentObjectBehaviuor; import Common.Database.Tables.FKCurrentObjectBehaviuor;
import Common.Database.Tables.FKDataBehaviour; import Common.Database.Tables.FKDataBehaviour;
import Common.Database.Tables.iDBTable; import Common.Database.Tables.iDBTable;
import Common.Visual.DataSetControlForm;
import _VisualDVM.TestingSystem.DVM.DVMCompilationOption.DVMCompilationOption; import _VisualDVM.TestingSystem.DVM.DVMCompilationOption.DVMCompilationOption;
import javax.swing.*;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
public class DVMCompilationOptionsSetsDBTable extends iDBTable<DVMCompilationOptionsSet> { public class DVMCompilationOptionsSetsDBTable extends iDBTable<DVMCompilationOptionsSet> {
public DVMCompilationOptionsSetsDBTable() { public DVMCompilationOptionsSetsDBTable() {

View File

@@ -11,6 +11,8 @@ public class DVMEnvironment extends iDBObject {
name = name_in; name = name_in;
value = value_in; value = value_in;
} }
public DVMEnvironment() {
}
@Override @Override
public void SynchronizeFields(DBObject src) { public void SynchronizeFields(DBObject src) {
super.SynchronizeFields(src); super.SynchronizeFields(src);
@@ -19,8 +21,6 @@ public class DVMEnvironment extends iDBObject {
value = src_.value; value = src_.value;
dvmenvironmentsset_id = src_.dvmenvironmentsset_id; dvmenvironmentsset_id = src_.dvmenvironmentsset_id;
} }
public DVMEnvironment() {
}
public String print() { public String print() {
return name + "=" + Utils_.DQuotes(value); return name + "=" + Utils_.DQuotes(value);
} }

View File

@@ -1,12 +1,5 @@
package _VisualDVM.TestingSystem.DVM.DVMEnvironment; package _VisualDVM.TestingSystem.DVM.DVMEnvironment;
import Common.Database.Objects.DBObject;
import Common.Database.Tables.FKBehaviour;
import Common.Database.Tables.FKCurrentObjectBehaviuor;
import Common.Database.Tables.FKDataBehaviour;
import Common.Database.Tables.iDBTable; import Common.Database.Tables.iDBTable;
import _VisualDVM.TestingSystem.DVM.DVMCompilationOption.DVMCompilationOption;
import java.util.LinkedHashMap;
public class DVMEnvironmentsDBTable extends iDBTable<DVMEnvironment> { public class DVMEnvironmentsDBTable extends iDBTable<DVMEnvironment> {
public DVMEnvironmentsDBTable() { public DVMEnvironmentsDBTable() {
super(DVMEnvironment.class); super(DVMEnvironment.class);

View File

@@ -15,7 +15,6 @@ public class DVMEnvironmentsSet extends iDBObject {
dvmsettings_id = dvmSettings.id; dvmsettings_id = dvmSettings.id;
} }
public DVMEnvironmentsSet() { public DVMEnvironmentsSet() {
} }
@Override @Override
public void SynchronizeFields(DBObject src) { public void SynchronizeFields(DBObject src) {

View File

@@ -11,8 +11,6 @@ import _VisualDVM.GlobalData.Machine.Machine;
import _VisualDVM.GlobalData.Machine.MachineType; import _VisualDVM.GlobalData.Machine.MachineType;
import _VisualDVM.GlobalData.Tasks.TaskState; import _VisualDVM.GlobalData.Tasks.TaskState;
import _VisualDVM.GlobalData.User.User; import _VisualDVM.GlobalData.User.User;
import _VisualDVM.ServerObjectsCache.DVMSettingsCache;
import _VisualDVM.ServerObjectsCache.VisualCaches;
import _VisualDVM.TestingSystem.Common.Configuration.Configuration; import _VisualDVM.TestingSystem.Common.Configuration.Configuration;
import _VisualDVM.TestingSystem.Common.Group.Group; import _VisualDVM.TestingSystem.Common.Group.Group;
import _VisualDVM.TestingSystem.Common.TasksPackageState; import _VisualDVM.TestingSystem.Common.TasksPackageState;

View File

@@ -1,7 +1,5 @@
package _VisualDVM.TestingSystem.DVM.DVMSettings; package _VisualDVM.TestingSystem.DVM.DVMSettings;
import Common.Database.Objects.DBObject; import Common.Database.Objects.DBObject;
import _VisualDVM.GlobalData.CompilerEnvironment.Json.EnvironmentsSetJson;
import _VisualDVM.GlobalData.CompilerOption.Json.OptionsSetJson;
import _VisualDVM.GlobalData.RunConfiguration.RunConfiguration; import _VisualDVM.GlobalData.RunConfiguration.RunConfiguration;
import _VisualDVM.TestingSystem.Common.Settings.Settings; import _VisualDVM.TestingSystem.Common.Settings.Settings;
import com.sun.org.glassfish.gmbal.Description; import com.sun.org.glassfish.gmbal.Description;

View File

@@ -1,13 +1,11 @@
package _VisualDVM.TestingSystem.DVM.DVMSettings.UI; package _VisualDVM.TestingSystem.DVM.DVMSettings.UI;
import Common.MainModule_; import Common.MainModule_;
import Common.Utils.Utils_;
import Common.Visual.TextField.StyledTextField; import Common.Visual.TextField.StyledTextField;
import Common.Visual.Windows.Dialog.DialogFields; import Common.Visual.Windows.Dialog.DialogFields;
import _VisualDVM.GlobalData.CompilerEnvironment.EnvironmentsLinesSet; import _VisualDVM.GlobalData.CompilerEnvironment.EnvironmentsLinesSet;
import _VisualDVM.GlobalData.CompilerEnvironment.Json.EnvironmentsSetJson; import _VisualDVM.GlobalData.CompilerEnvironment.Json.EnvironmentsSetJson;
import _VisualDVM.GlobalData.CompilerOption.Json.OptionsSetJson; import _VisualDVM.GlobalData.CompilerOption.Json.OptionsSetJson;
import _VisualDVM.GlobalData.CompilerOption.OptionsLinesSet; import _VisualDVM.GlobalData.CompilerOption.OptionsLinesSet;
import _VisualDVM.TestingSystem.DVM.DVMCompilationOptionsSet.DVMCompilationOptionsSet;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;

View File

@@ -9,8 +9,8 @@ public class SapforConfigurationFields implements DialogFields {
public JTextField tfName; public JTextField tfName;
public JSpinner sTransformationMaxtime; public JSpinner sTransformationMaxtime;
public JSpinner sKernels; public JSpinner sKernels;
private JPanel content;
public JCheckBox cbGroupsOnly; public JCheckBox cbGroupsOnly;
private JPanel content;
public SapforConfigurationFields() { public SapforConfigurationFields() {
sKernels.setModel(new SpinnerNumberModel(1, 1, sKernels.setModel(new SpinnerNumberModel(1, 1,
Constants.testingMaxKernels, Constants.testingMaxKernels,

View File

@@ -2,7 +2,6 @@ package _VisualDVM.TestingSystem.SAPFOR.SapforPackageConfiguration;
import Common.CommonConstants; import Common.CommonConstants;
import Common.Database.Objects.DBObject; import Common.Database.Objects.DBObject;
import Common.Database.Objects.iDBObject; import Common.Database.Objects.iDBObject;
import _VisualDVM.TestingSystem.DVM.DVMPackageConfiguration.DVMPackageConfiguration;
import _VisualDVM.TestingSystem.SAPFOR.SapforConfiguration.SapforConfiguration; import _VisualDVM.TestingSystem.SAPFOR.SapforConfiguration.SapforConfiguration;
public class SapforPackageConfiguration extends iDBObject { public class SapforPackageConfiguration extends iDBObject {
public int sapforpackage_id = CommonConstants.Nan; public int sapforpackage_id = CommonConstants.Nan;

View File

@@ -15,13 +15,14 @@ import javafx.util.Pair;
import org.fife.ui.rtextarea.RTextScrollPane; import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*; import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Highlighter; import javax.swing.text.Highlighter;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
public abstract class ComparisonForm<T> { public abstract class ComparisonForm<T> {
final String separator = "\u200B";
final char cseparator = '\u200B';
public Class<T> t; //класс объектов. public Class<T> t; //класс объектов.
//-->> //-->>
public Vector<String> lines = new Vector<>(); //строки с учетом/неучетом пробелов. для сравнения public Vector<String> lines = new Vector<>(); //строки с учетом/неучетом пробелов. для сравнения
@@ -34,6 +35,10 @@ public abstract class ComparisonForm<T> {
protected T object = null; protected T object = null;
//-->> //-->>
protected BaseEditor Body; protected BaseEditor Body;
//невидимый пробел https://translated.turbopages.org/proxy_u/en-ru.ru.898e1daf-67e318c0-3fccff8a-74722d776562/https/stackoverflow.com/questions/17978720/invisible-characters-ascii
//--->>
// protected Object ownScrollModel = null;
protected Vector<Pair<Integer, Integer>> diffs = new Vector<>();
//-->> //-->>
ComparisonForm<T> this_ = null; //? ComparisonForm<T> this_ = null; //?
ComparisonForm<T> slave = null; ComparisonForm<T> slave = null;
@@ -48,22 +53,6 @@ public abstract class ComparisonForm<T> {
//----- //-----
private boolean events_on = false;//относится только к мастеру, отвечает за скроллы. private boolean events_on = false;//относится только к мастеру, отвечает за скроллы.
private int current_diff_num = -1; private int current_diff_num = -1;
final String separator = "\u200B";
final char cseparator = '\u200B';
//невидимый пробел https://translated.turbopages.org/proxy_u/en-ru.ru.898e1daf-67e318c0-3fccff8a-74722d776562/https/stackoverflow.com/questions/17978720/invisible-characters-ascii
//--->>
// protected Object ownScrollModel = null;
protected Vector<Pair<Integer, Integer>> diffs = new Vector<>();
//---<<
private void ShowCurrentDiff() {
try {
int diff_line = Body.getLineOfOffset(diffs.get(current_diff_num).getKey());
Body.gotoLine_(diff_line);
}
catch (Exception ex){
ex.printStackTrace();
}
}
public ComparisonForm(Class<T> t_in, ComparisonForm<T> slave_in) { public ComparisonForm(Class<T> t_in, ComparisonForm<T> slave_in) {
//- //-
Body = new BaseEditor(); Body = new BaseEditor();
@@ -130,6 +119,15 @@ public abstract class ComparisonForm<T> {
} }
}); });
} }
//---<<
private void ShowCurrentDiff() {
try {
int diff_line = Body.getLineOfOffset(diffs.get(current_diff_num).getKey());
Body.gotoLine_(diff_line);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public JPanel getContent() { public JPanel getContent() {
return content; return content;
} }
@@ -234,7 +232,6 @@ public abstract class ComparisonForm<T> {
dif_end = CommonConstants.Nan; dif_end = CommonConstants.Nan;
break; break;
} }
} else { } else {
//поиск //поиск
switch (c) { switch (c) {

View File

@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib; package com.github.difflib;
import com.github.difflib.algorithm.DiffAlgorithmFactory; import com.github.difflib.algorithm.DiffAlgorithmFactory;
import com.github.difflib.algorithm.DiffAlgorithmI; import com.github.difflib.algorithm.DiffAlgorithmI;
import com.github.difflib.algorithm.DiffAlgorithmListener; import com.github.difflib.algorithm.DiffAlgorithmListener;
@@ -22,23 +21,19 @@ import com.github.difflib.algorithm.myers.MyersDiff;
import com.github.difflib.patch.AbstractDelta; import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.Patch; import com.github.difflib.patch.Patch;
import com.github.difflib.patch.PatchFailedException; import com.github.difflib.patch.PatchFailedException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.*;
import java.util.function.BiPredicate;
/** /**
* Utility class to implement the difference and patching engine. * Utility class to implement the difference and patching engine.
*/ */
public final class DiffUtils { public final class DiffUtils {
/** /**
* This factory generates the DEFAULT_DIFF algorithm for all these routines. * This factory generates the DEFAULT_DIFF algorithm for all these routines.
*/ */
static DiffAlgorithmFactory DEFAULT_DIFF = MyersDiff.factory(); static DiffAlgorithmFactory DEFAULT_DIFF = MyersDiff.factory();
private DiffUtils() {
}
/** /**
* Sets the default diff algorithm factory to be used by all diff routines. * Sets the default diff algorithm factory to be used by all diff routines.
* *
@@ -47,7 +42,6 @@ public final class DiffUtils {
public static void withDefaultDiffAlgorithmFactory(DiffAlgorithmFactory factory) { public static void withDefaultDiffAlgorithmFactory(DiffAlgorithmFactory factory) {
DEFAULT_DIFF = factory; DEFAULT_DIFF = factory;
} }
/** /**
* Computes the difference between two sequences of elements using the default diff algorithm. * Computes the difference between two sequences of elements using the default diff algorithm.
* *
@@ -60,7 +54,6 @@ public final class DiffUtils {
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) { public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) {
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), progress); return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), progress);
} }
/** /**
* Computes the difference between two sequences of elements using the default diff algorithm. * Computes the difference between two sequences of elements using the default diff algorithm.
* *
@@ -72,7 +65,6 @@ public final class DiffUtils {
public static <T> Patch<T> diff(List<T> original, List<T> revised) { public static <T> Patch<T> diff(List<T> original, List<T> revised) {
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null); return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null);
} }
/** /**
* Computes the difference between two sequences of elements using the default diff algorithm. * Computes the difference between two sequences of elements using the default diff algorithm.
* *
@@ -85,7 +77,6 @@ public final class DiffUtils {
public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) { public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) {
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null, includeEqualParts); return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null, includeEqualParts);
} }
/** /**
* Computes the difference between two strings using the default diff algorithm. * Computes the difference between two strings using the default diff algorithm.
* *
@@ -100,7 +91,6 @@ public final class DiffUtils {
Arrays.asList(sourceText.split("\n")), Arrays.asList(sourceText.split("\n")),
Arrays.asList(targetText.split("\n")), progress); Arrays.asList(targetText.split("\n")), progress);
} }
/** /**
* Computes the difference between the original and revised list of elements * Computes the difference between the original and revised list of elements
* with default diff algorithm * with default diff algorithm
@@ -121,12 +111,10 @@ public final class DiffUtils {
} }
return DiffUtils.diff(source, target, new MyersDiff<>()); return DiffUtils.diff(source, target, new MyersDiff<>());
} }
public static <T> Patch<T> diff(List<T> original, List<T> revised, 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); return diff(original, revised, algorithm, progress, false);
} }
/** /**
* Computes the difference between the original and revised list of elements * Computes the difference between the original and revised list of elements
* with default diff algorithm * with default diff algorithm
@@ -145,11 +133,8 @@ public final class DiffUtils {
Objects.requireNonNull(original, "original must not be null"); Objects.requireNonNull(original, "original must not be null");
Objects.requireNonNull(revised, "revised must not be null"); Objects.requireNonNull(revised, "revised must not be null");
Objects.requireNonNull(algorithm, "algorithm must not be null"); Objects.requireNonNull(algorithm, "algorithm must not be null");
return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress), includeEqualParts); return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress), includeEqualParts);
} }
/** /**
* Computes the difference between the original and revised list of elements * Computes the difference between the original and revised list of elements
* with default diff algorithm * with default diff algorithm
@@ -163,7 +148,6 @@ public final class DiffUtils {
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmI<T> algorithm) { public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmI<T> algorithm) {
return diff(original, revised, algorithm, null); return diff(original, revised, algorithm, null);
} }
/** /**
* Computes the difference between the given texts inline. This one uses the * Computes the difference between the given texts inline. This one uses the
* "trick" to make out of texts lists of characters, like DiffRowGenerator * "trick" to make out of texts lists of characters, like DiffRowGenerator
@@ -190,7 +174,6 @@ public final class DiffUtils {
} }
return patch; return patch;
} }
/** /**
* Applies the given patch to the original list and returns the revised list. * Applies the given patch to the original list and returns the revised list.
* *
@@ -203,7 +186,6 @@ public final class DiffUtils {
throws PatchFailedException { throws PatchFailedException {
return patch.applyTo(original); return patch.applyTo(original);
} }
/** /**
* Applies the given patch to the revised list and returns the original list. * Applies the given patch to the revised list and returns the original list.
* *
@@ -215,14 +197,10 @@ public final class DiffUtils {
public static <T> List<T> unpatch(List<T> revised, Patch<T> patch) { public static <T> List<T> unpatch(List<T> revised, Patch<T> patch) {
return patch.restore(revised); return patch.restore(revised);
} }
private static List<String> compressLines(List<String> lines, String delimiter) { private static List<String> compressLines(List<String> lines, String delimiter) {
if (lines.isEmpty()) { if (lines.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
return Collections.singletonList(String.join(delimiter, lines)); return Collections.singletonList(String.join(delimiter, lines));
} }
private DiffUtils() {
}
} }

View File

@@ -14,31 +14,24 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib; package com.github.difflib;
import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.ChangeDelta; import com.github.difflib.patch.ChangeDelta;
import com.github.difflib.patch.Chunk; import com.github.difflib.patch.Chunk;
import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.Patch; import com.github.difflib.patch.Patch;
import java.util.ArrayList; import java.util.*;
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.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
*
* @author toben * @author toben
*/ */
public final class UnifiedDiffUtils { public final class UnifiedDiffUtils {
private static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern private static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern
.compile("^@@\\s+-(\\d+)(?:,(\\d+))?\\s+\\+(\\d+)(?:,(\\d+))?\\s+@@.*$"); .compile("^@@\\s+-(\\d+)(?:,(\\d+))?\\s+\\+(\\d+)(?:,(\\d+))?\\s+@@.*$");
private static final String NULL_FILE_INDICATOR = "/dev/null"; private static final String NULL_FILE_INDICATOR = "/dev/null";
private UnifiedDiffUtils() {
}
/** /**
* Parse the given text in unified format and creates the list of deltas for it. * Parse the given text in unified format and creates the list of deltas for it.
* *
@@ -49,7 +42,6 @@ public final class UnifiedDiffUtils {
boolean inPrelude = true; boolean inPrelude = true;
List<String[]> rawChunk = new ArrayList<>(); List<String[]> rawChunk = new ArrayList<>();
Patch<String> patch = new Patch<>(); Patch<String> patch = new Patch<>();
int old_ln = 0; int old_ln = 0;
int new_ln = 0; int new_ln = 0;
String tag; String tag;
@@ -69,7 +61,6 @@ public final class UnifiedDiffUtils {
// Parse the @@ header // Parse the @@ header
old_ln = m.group(1) == null ? 1 : Integer.parseInt(m.group(1)); old_ln = m.group(1) == null ? 1 : Integer.parseInt(m.group(1));
new_ln = m.group(3) == null ? 1 : Integer.parseInt(m.group(3)); new_ln = m.group(3) == null ? 1 : Integer.parseInt(m.group(3));
if (old_ln == 0) { if (old_ln == 0) {
old_ln = 1; old_ln = 1;
} }
@@ -88,20 +79,16 @@ public final class UnifiedDiffUtils {
} }
} }
} }
// Process the lines in the last chunk // Process the lines in the last chunk
processLinesInPrevChunk(rawChunk, patch, old_ln, new_ln); processLinesInPrevChunk(rawChunk, patch, old_ln, new_ln);
return patch; return patch;
} }
private static void processLinesInPrevChunk(List<String[]> rawChunk, Patch<String> patch, int old_ln, int new_ln) { private static void processLinesInPrevChunk(List<String[]> rawChunk, Patch<String> patch, int old_ln, int new_ln) {
String tag; String tag;
String rest; String rest;
if (!rawChunk.isEmpty()) { if (!rawChunk.isEmpty()) {
List<String> oldChunkLines = new ArrayList<>(); List<String> oldChunkLines = new ArrayList<>();
List<String> newChunkLines = new ArrayList<>(); List<String> newChunkLines = new ArrayList<>();
List<Integer> removePosition = new ArrayList<>(); List<Integer> removePosition = new ArrayList<>();
List<Integer> addPosition = new ArrayList<>(); List<Integer> addPosition = new ArrayList<>();
int removeNum = 0; int removeNum = 0;
@@ -130,7 +117,6 @@ public final class UnifiedDiffUtils {
rawChunk.clear(); rawChunk.clear();
} }
} }
/** /**
* generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format * generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format
* text representing the Patch. Author: Bill James (tankerbay@gmail.com). * text representing the Patch. Author: Bill James (tankerbay@gmail.com).
@@ -149,10 +135,8 @@ public final class UnifiedDiffUtils {
List<String> ret = new ArrayList<>(); List<String> ret = new ArrayList<>();
ret.add("--- " + Optional.ofNullable(originalFileName).orElse(NULL_FILE_INDICATOR)); ret.add("--- " + Optional.ofNullable(originalFileName).orElse(NULL_FILE_INDICATOR));
ret.add("+++ " + Optional.ofNullable(revisedFileName).orElse(NULL_FILE_INDICATOR)); ret.add("+++ " + Optional.ofNullable(revisedFileName).orElse(NULL_FILE_INDICATOR));
List<AbstractDelta<String>> patchDeltas = new ArrayList<>( List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
patch.getDeltas()); patch.getDeltas());
// code outside the if block also works for single-delta issues. // code outside the if block also works for single-delta issues.
List<AbstractDelta<String>> deltas = new ArrayList<>(); // current List<AbstractDelta<String>> deltas = new ArrayList<>(); // current
// list // list
@@ -170,7 +154,6 @@ public final class UnifiedDiffUtils {
// position // position
// of // of
// the first Delta // the first Delta
// Check if the next Delta is too close to the current // Check if the next Delta is too close to the current
// position. // position.
// And if it is, add it to the current set // And if it is, add it to the current set
@@ -190,7 +173,6 @@ public final class UnifiedDiffUtils {
} }
delta = nextDelta; delta = nextDelta;
} }
} }
// don't forget to process the last set of Deltas // don't forget to process the last set of Deltas
List<String> curBlock = processDeltas(originalLines, deltas, List<String> curBlock = processDeltas(originalLines, deltas,
@@ -200,7 +182,6 @@ public final class UnifiedDiffUtils {
} }
return new ArrayList<>(); return new ArrayList<>();
} }
/** /**
* processDeltas takes a list of Deltas and outputs them together in a single block of * processDeltas takes a list of Deltas and outputs them together in a single block of
* Unified-Diff-format text. Author: Bill James (tankerbay@gmail.com). * Unified-Diff-format text. Author: Bill James (tankerbay@gmail.com).
@@ -216,7 +197,6 @@ public final class UnifiedDiffUtils {
int origTotal = 0; // counter for total lines output from Original int origTotal = 0; // counter for total lines output from Original
int revTotal = 0; // counter for total lines output from Original int revTotal = 0; // counter for total lines output from Original
int line; int line;
AbstractDelta<String> curDelta = deltas.get(0); AbstractDelta<String> curDelta = deltas.get(0);
int origStart; int origStart;
if (newFile) { if (newFile) {
@@ -228,30 +208,25 @@ public final class UnifiedDiffUtils {
origStart = 1; origStart = 1;
} }
} }
int revStart = curDelta.getTarget().getPosition() + 1 - contextSize; int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
if (revStart < 1) { if (revStart < 1) {
revStart = 1; revStart = 1;
} }
// find the start of the wrapper context code // find the start of the wrapper context code
int contextStart = curDelta.getSource().getPosition() - contextSize; int contextStart = curDelta.getSource().getPosition() - contextSize;
if (contextStart < 0) { if (contextStart < 0) {
contextStart = 0; // clamp to the start of the file contextStart = 0; // clamp to the start of the file
} }
// output the context before the first Delta // output the context before the first Delta
for (line = contextStart; line < curDelta.getSource().getPosition(); line++) { // for (line = contextStart; line < curDelta.getSource().getPosition(); line++) { //
buffer.add(" " + origLines.get(line)); buffer.add(" " + origLines.get(line));
origTotal++; origTotal++;
revTotal++; revTotal++;
} }
// output the first Delta // output the first Delta
buffer.addAll(getDeltaText(curDelta)); buffer.addAll(getDeltaText(curDelta));
origTotal += curDelta.getSource().getLines().size(); origTotal += curDelta.getSource().getLines().size();
revTotal += curDelta.getTarget().getLines().size(); revTotal += curDelta.getTarget().getLines().size();
int deltaIndex = 1; int deltaIndex = 1;
while (deltaIndex < deltas.size()) { // for each of the other Deltas while (deltaIndex < deltas.size()) { // for each of the other Deltas
AbstractDelta<String> nextDelta = deltas.get(deltaIndex); AbstractDelta<String> nextDelta = deltas.get(deltaIndex);
@@ -270,7 +245,6 @@ public final class UnifiedDiffUtils {
curDelta = nextDelta; curDelta = nextDelta;
deltaIndex++; deltaIndex++;
} }
// Now output the post-Delta context code, clamping the end of the file // Now output the post-Delta context code, clamping the end of the file
contextStart = curDelta.getSource().getPosition() contextStart = curDelta.getSource().getPosition()
+ curDelta.getSource().getLines().size(); + curDelta.getSource().getLines().size();
@@ -280,7 +254,6 @@ public final class UnifiedDiffUtils {
origTotal++; origTotal++;
revTotal++; revTotal++;
} }
// Create and insert the block header, conforming to the Unified Diff // Create and insert the block header, conforming to the Unified Diff
// standard // standard
StringBuilder header = new StringBuilder(); StringBuilder header = new StringBuilder();
@@ -294,10 +267,8 @@ public final class UnifiedDiffUtils {
header.append(revTotal); header.append(revTotal);
header.append(" @@"); header.append(" @@");
buffer.add(0, header.toString()); buffer.add(0, header.toString());
return buffer; return buffer;
} }
/** /**
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter. Author: Bill James (tankerbay@gmail.com). * getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter. Author: Bill James (tankerbay@gmail.com).
* *
@@ -314,13 +285,9 @@ public final class UnifiedDiffUtils {
} }
return buffer; return buffer;
} }
private UnifiedDiffUtils() {
}
/** /**
* Compare the differences between two files and return to the original file and diff format * Compare the differences between two files and return to the original file and diff format
* * <p>
* (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. * (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. * 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, * Also, this will be very easy and useful for making side-by-side comparison display applications,
@@ -329,16 +296,13 @@ public final class UnifiedDiffUtils {
* *
* @param original Original file content * @param original Original file content
* @param revised revised file content * @param revised revised file content
*
*/ */
public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised) { public static List<String> generateOriginalAndDiff(List<String> original, List<String> revised) {
return generateOriginalAndDiff(original, revised, null, null); return generateOriginalAndDiff(original, revised, null, null);
} }
/** /**
* Compare the differences between two files and return to the original file and diff format * Compare the differences between two files and return to the original file and diff format
* * <p>
* (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. * (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. * 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, * Also, this will be very easy and useful for making side-by-side comparison display applications,
@@ -372,7 +336,6 @@ public final class UnifiedDiffUtils {
List<String> originalWithPrefix = original.stream().map(v -> " " + v).collect(Collectors.toList()); List<String> originalWithPrefix = original.stream().map(v -> " " + v).collect(Collectors.toList());
return insertOrig(originalWithPrefix, unifiedDiff); return insertOrig(originalWithPrefix, unifiedDiff);
} }
//Insert the diff format to the original file //Insert the diff format to the original file
private static List<String> insertOrig(List<String> original, List<String> unifiedDiff) { private static List<String> insertOrig(List<String> original, List<String> unifiedDiff) {
List<String> result = new ArrayList<>(); List<String> result = new ArrayList<>();
@@ -401,7 +364,6 @@ public final class UnifiedDiffUtils {
insertOrig(diffList, result, original); insertOrig(diffList, result, original);
return result; return result;
} }
//Insert the diff format to the original file //Insert the diff format to the original file
private static void insertOrig(List<List<String>> diffList, List<String> result, List<String> original) { private static void insertOrig(List<List<String>> diffList, List<String> result, List<String> original) {
for (int i = 0; i < diffList.size(); i++) { for (int i = 0; i < diffList.size(); i++) {
@@ -429,14 +391,12 @@ public final class UnifiedDiffUtils {
} }
} }
} }
//Insert the unchanged content in the source file into result //Insert the unchanged content in the source file into result
private static void insert(List<String> result, List<String> noChangeContent) { private static void insert(List<String> result, List<String> noChangeContent) {
for (String ins : noChangeContent) { for (String ins : noChangeContent) {
result.add(ins); result.add(ins);
} }
} }
//Parse the line containing @@ to get the modified line number to delete or add a few lines //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) { private static Map<String, Integer> getRowMap(String str) {
Map<String, Integer> map = new HashMap<>(); Map<String, Integer> map = new HashMap<>();
@@ -452,7 +412,6 @@ public final class UnifiedDiffUtils {
} }
return map; return map;
} }
//Get the specified part of the line from the original file //Get the specified part of the line from the original file
private static List<String> getOrigList(List<String> originalWithPrefix, int start, int end) { private static List<String> getOrigList(List<String> originalWithPrefix, int start, int end) {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();

View File

@@ -14,21 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm; package com.github.difflib.algorithm;
import com.github.difflib.patch.DeltaType; import com.github.difflib.patch.DeltaType;
/** /**
*
* @author <a href="t.warneke@gmx.net">Tobias Warneke</a> * @author <a href="t.warneke@gmx.net">Tobias Warneke</a>
*/ */
public class Change { public class Change {
public final DeltaType deltaType; public final DeltaType deltaType;
public final int startOriginal; public final int startOriginal;
public final int endOriginal; public final int endOriginal;
public final int startRevised; public final int startRevised;
public final int endRevised; public final int endRevised;
public Change(DeltaType deltaType, int startOriginal, int endOriginal, int startRevised, int endRevised) { public Change(DeltaType deltaType, int startOriginal, int endOriginal, int startRevised, int endRevised) {
this.deltaType = deltaType; this.deltaType = deltaType;
this.startOriginal = startOriginal; this.startOriginal = startOriginal;
@@ -36,11 +31,9 @@ public class Change {
this.startRevised = startRevised; this.startRevised = startRevised;
this.endRevised = endRevised; this.endRevised = endRevised;
} }
public Change withEndOriginal(int endOriginal) { public Change withEndOriginal(int endOriginal) {
return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised); return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised);
} }
public Change withEndRevised(int endRevised) { public Change withEndRevised(int endRevised) {
return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised); return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised);
} }

View File

@@ -14,16 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm; package com.github.difflib.algorithm;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
/** /**
* Tool to create new instances of a diff algorithm. This one is only needed at the moment to * Tool to create new instances of a diff algorithm. This one is only needed at the moment to
* set DiffUtils default diff algorithm. * set DiffUtils default diff algorithm.
*
* @author tw * @author tw
*/ */
public interface DiffAlgorithmFactory { public interface DiffAlgorithmFactory {
<T> DiffAlgorithmI<T> create(); <T> DiffAlgorithmI<T> create();
<T> DiffAlgorithmI<T> create(BiPredicate<T, T> equalizer); <T> DiffAlgorithmI<T> create(BiPredicate<T, T> equalizer);
} }

View File

@@ -14,18 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm; package com.github.difflib.algorithm;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
* Interface of a diff algorithm. * Interface of a diff algorithm.
* *
* @author Tobias Warneke (t.warneke@gmx.net)
* @param <T> type of data that is diffed. * @param <T> type of data that is diffed.
* @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public interface DiffAlgorithmI<T> { public interface DiffAlgorithmI<T> {
/** /**
* Computes the changeset to patch the source list to the target list. * Computes the changeset to patch the source list to the target list.
* *
@@ -35,7 +32,6 @@ public interface DiffAlgorithmI<T> {
* @return * @return
*/ */
List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress); List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress);
/** /**
* Simple extension to compute a changeset using arrays. * Simple extension to compute a changeset using arrays.
* *

View File

@@ -14,18 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm; package com.github.difflib.algorithm;
/** /**
*
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public interface DiffAlgorithmListener { public interface DiffAlgorithmListener {
void diffStart(); void diffStart();
/** /**
* This is a step within the diff algorithm. Due to different implementations the value * This is a step within the diff algorithm. Due to different implementations the value
* is not strict incrementing to the max and is not garantee to reach the max. It could * is not strict incrementing to the max and is not garantee to reach the max. It could
* stop before. * stop before.
*
* @param value * @param value
* @param max * @param max
*/ */

View File

@@ -14,44 +14,55 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm.myers; package com.github.difflib.algorithm.myers;
import com.github.difflib.algorithm.Change; import com.github.difflib.algorithm.Change;
import com.github.difflib.algorithm.DiffAlgorithmFactory; import com.github.difflib.algorithm.DiffAlgorithmFactory;
import com.github.difflib.algorithm.DiffAlgorithmI; import com.github.difflib.algorithm.DiffAlgorithmI;
import com.github.difflib.algorithm.DiffAlgorithmListener; import com.github.difflib.algorithm.DiffAlgorithmListener;
import com.github.difflib.patch.DeltaType; import com.github.difflib.patch.DeltaType;
import com.github.difflib.patch.Patch; import com.github.difflib.patch.Patch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
/** /**
* A clean-room implementation of Eugene Myers greedy differencing algorithm. * A clean-room implementation of Eugene Myers greedy differencing algorithm.
*/ */
public final class MyersDiff<T> implements DiffAlgorithmI<T> { public final class MyersDiff<T> implements DiffAlgorithmI<T> {
private final BiPredicate<T, T> equalizer; private final BiPredicate<T, T> equalizer;
public MyersDiff() { public MyersDiff() {
equalizer = Object::equals; equalizer = Object::equals;
} }
public MyersDiff(final BiPredicate<T, T> equalizer) { public MyersDiff(final BiPredicate<T, T> equalizer) {
Objects.requireNonNull(equalizer, "equalizer must not be null"); Objects.requireNonNull(equalizer, "equalizer must not be null");
this.equalizer = equalizer; this.equalizer = equalizer;
} }
/**
* 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);
}
};
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p>
* Return empty diff if get the error while procession the difference. * Return empty diff if get the error while procession the difference.
*/ */
@Override @Override
public List<Change> computeDiff(final List<T> source, final List<T> target, DiffAlgorithmListener progress) { public List<Change> computeDiff(final List<T> source, final List<T> target, DiffAlgorithmListener progress) {
Objects.requireNonNull(source, "source list must not be null"); Objects.requireNonNull(source, "source list must not be null");
Objects.requireNonNull(target, "target list must not be null"); Objects.requireNonNull(target, "target list must not be null");
if (progress != null) { if (progress != null) {
progress.diffStart(); progress.diffStart();
} }
@@ -62,7 +73,6 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
} }
return result; return result;
} }
/** /**
* Computes the minimum diffpath that expresses de differences between the * Computes the minimum diffpath that expresses de differences between the
* original and revised sequences, according to Gene Myers differencing * original and revised sequences, according to Gene Myers differencing
@@ -76,16 +86,13 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
private PathNode buildPath(final List<T> orig, final List<T> rev, DiffAlgorithmListener progress) { private PathNode buildPath(final List<T> orig, final List<T> rev, DiffAlgorithmListener progress) {
Objects.requireNonNull(orig, "original sequence is null"); Objects.requireNonNull(orig, "original sequence is null");
Objects.requireNonNull(rev, "revised sequence is null"); Objects.requireNonNull(rev, "revised sequence is null");
// these are local constants // these are local constants
final int N = orig.size(); final int N = orig.size();
final int M = rev.size(); final int M = rev.size();
final int MAX = N + M + 1; final int MAX = N + M + 1;
final int size = 1 + 2 * MAX; final int size = 1 + 2 * MAX;
final int middle = size / 2; final int middle = size / 2;
final PathNode diagonal[] = new PathNode[size]; final PathNode diagonal[] = new PathNode[size];
diagonal[middle + 1] = new PathNode(0, -1, true, true, null); diagonal[middle + 1] = new PathNode(0, -1, true, true, null);
for (int d = 0; d < MAX; d++) { for (int d = 0; d < MAX; d++) {
if (progress != null) { if (progress != null) {
@@ -97,7 +104,6 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
final int kminus = kmiddle - 1; final int kminus = kmiddle - 1;
PathNode prev; PathNode prev;
int i; int i;
if ((k == -d) || (k != d && diagonal[kminus].i < diagonal[kplus].i)) { if ((k == -d) || (k != d && diagonal[kminus].i < diagonal[kplus].i)) {
i = diagonal[kplus].i; i = diagonal[kplus].i;
prev = diagonal[kplus]; prev = diagonal[kplus];
@@ -105,24 +111,17 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
i = diagonal[kminus].i + 1; i = diagonal[kminus].i + 1;
prev = diagonal[kminus]; prev = diagonal[kminus];
} }
diagonal[kminus] = null; // no longer used diagonal[kminus] = null; // no longer used
int j = i - k; int j = i - k;
PathNode node = new PathNode(i, j, false, false, prev); PathNode node = new PathNode(i, j, false, false, prev);
while (i < N && j < M && equalizer.test(orig.get(i), rev.get(j))) { while (i < N && j < M && equalizer.test(orig.get(i), rev.get(j))) {
i++; i++;
j++; j++;
} }
if (i != node.i) { if (i != node.i) {
node = new PathNode(i, j, true, false, node); node = new PathNode(i, j, true, false, node);
} }
diagonal[kmiddle] = node; diagonal[kmiddle] = node;
if (i >= N && j >= M) { if (i >= N && j >= M) {
return diagonal[kmiddle]; return diagonal[kmiddle];
} }
@@ -132,7 +131,6 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
// According to Myers, this cannot happen // According to Myers, this cannot happen
throw new IllegalStateException("could not find a diff path"); throw new IllegalStateException("could not find a diff path");
} }
/** /**
* Constructs a {@link Patch} from a difference path. * Constructs a {@link Patch} from a difference path.
* *
@@ -147,7 +145,6 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
Objects.requireNonNull(actualPath, "path is null"); Objects.requireNonNull(actualPath, "path is null");
Objects.requireNonNull(orig, "original sequence is null"); Objects.requireNonNull(orig, "original sequence is null");
Objects.requireNonNull(rev, "revised sequence is null"); Objects.requireNonNull(rev, "revised sequence is null");
PathNode path = actualPath; PathNode path = actualPath;
List<Change> changes = new ArrayList<>(); List<Change> changes = new ArrayList<>();
if (path.isSnake()) { if (path.isSnake()) {
@@ -159,11 +156,9 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
} }
int i = path.i; int i = path.i;
int j = path.j; int j = path.j;
path = path.prev; path = path.prev;
int ianchor = path.i; int ianchor = path.i;
int janchor = path.j; int janchor = path.j;
if (ianchor == i && janchor != j) { if (ianchor == i && janchor != j) {
changes.add(new Change(DeltaType.INSERT, ianchor, i, janchor, j)); changes.add(new Change(DeltaType.INSERT, ianchor, i, janchor, j));
} else if (ianchor != i && janchor == j) { } else if (ianchor != i && janchor == j) {
@@ -171,30 +166,10 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
} else { } else {
changes.add(new Change(DeltaType.CHANGE, ianchor, i, janchor, j)); changes.add(new Change(DeltaType.CHANGE, ianchor, i, janchor, j));
} }
if (path.isSnake()) { if (path.isSnake()) {
path = path.prev; path = path.prev;
} }
} }
return changes; 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);
}
};
}
} }

View File

@@ -14,60 +14,65 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm.myers; package com.github.difflib.algorithm.myers;
import com.github.difflib.algorithm.Change; import com.github.difflib.algorithm.Change;
import com.github.difflib.algorithm.DiffAlgorithmFactory; import com.github.difflib.algorithm.DiffAlgorithmFactory;
import com.github.difflib.algorithm.DiffAlgorithmI; import com.github.difflib.algorithm.DiffAlgorithmI;
import com.github.difflib.algorithm.DiffAlgorithmListener; import com.github.difflib.algorithm.DiffAlgorithmListener;
import com.github.difflib.patch.DeltaType; import com.github.difflib.patch.DeltaType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
*
* @author tw * @author tw
*/ */
public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> { public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
private final BiPredicate<T, T> equalizer; private final BiPredicate<T, T> equalizer;
public MyersDiffWithLinearSpace() { public MyersDiffWithLinearSpace() {
equalizer = Object::equals; equalizer = Object::equals;
} }
public MyersDiffWithLinearSpace(final BiPredicate<T, T> equalizer) { public MyersDiffWithLinearSpace(final BiPredicate<T, T> equalizer) {
Objects.requireNonNull(equalizer, "equalizer must not be null"); Objects.requireNonNull(equalizer, "equalizer must not be null");
this.equalizer = equalizer; this.equalizer = equalizer;
} }
/**
* 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);
}
};
}
@Override @Override
public List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) { public List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) {
Objects.requireNonNull(source, "source list must not be null"); Objects.requireNonNull(source, "source list must not be null");
Objects.requireNonNull(target, "target list must not be null"); Objects.requireNonNull(target, "target list must not be null");
if (progress != null) { if (progress != null) {
progress.diffStart(); progress.diffStart();
} }
DiffData data = new DiffData(source, target); DiffData data = new DiffData(source, target);
int maxIdx = source.size() + target.size(); int maxIdx = source.size() + target.size();
buildScript(data, 0, source.size(), 0, target.size(), idx -> { buildScript(data, 0, source.size(), 0, target.size(), idx -> {
if (progress != null) { if (progress != null) {
progress.diffStep(idx, maxIdx); progress.diffStep(idx, maxIdx);
} }
}); });
if (progress != null) { if (progress != null) {
progress.diffEnd(); progress.diffEnd();
} }
return data.script; return data.script;
} }
private void buildScript(DiffData data, int start1, int end1, int start2, int end2, Consumer<Integer> progress) { private void buildScript(DiffData data, int start1, int end1, int start2, int end2, Consumer<Integer> progress) {
if (progress != null) { if (progress != null) {
progress.accept((end1 - start1) / 2 + (end2 - start2) / 2); progress.accept((end1 - start1) / 2 + (end2 - start2) / 2);
@@ -112,35 +117,29 @@ public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
buildScript(data, middle.end, end1, middle.end - middle.diag, end2, 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) { private Snake getMiddleSnake(DiffData data, int start1, int end1, int start2, int end2) {
final int m = end1 - start1; final int m = end1 - start1;
final int n = end2 - start2; final int n = end2 - start2;
if (m == 0 || n == 0) { if (m == 0 || n == 0) {
return null; return null;
} }
final int delta = m - n; final int delta = m - n;
final int sum = n + m; final int sum = n + m;
final int offset = (sum % 2 == 0 ? sum : sum + 1) / 2; final int offset = (sum % 2 == 0 ? sum : sum + 1) / 2;
data.vDown[1 + offset] = start1; data.vDown[1 + offset] = start1;
data.vUp[1 + offset] = end1 + 1; data.vUp[1 + offset] = end1 + 1;
for (int d = 0; d <= offset; ++d) { for (int d = 0; d <= offset; ++d) {
// Down // Down
for (int k = -d; k <= d; k += 2) { for (int k = -d; k <= d; k += 2) {
// First step // First step
final int i = k + offset; final int i = k + offset;
if (k == -d || k != d && data.vDown[i - 1] < data.vDown[i + 1]) { if (k == -d || k != d && data.vDown[i - 1] < data.vDown[i + 1]) {
data.vDown[i] = data.vDown[i + 1]; data.vDown[i] = data.vDown[i + 1];
} else { } else {
data.vDown[i] = data.vDown[i - 1] + 1; data.vDown[i] = data.vDown[i - 1] + 1;
} }
int x = data.vDown[i]; int x = data.vDown[i];
int y = x - start1 + start2 - k; int y = x - start1 + start2 - k;
while (x < end1 && y < end2 && equalizer.test(data.source.get(x), data.target.get(y))) { while (x < end1 && y < end2 && equalizer.test(data.source.get(x), data.target.get(y))) {
data.vDown[i] = ++x; data.vDown[i] = ++x;
++y; ++y;
@@ -152,7 +151,6 @@ public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
} }
} }
} }
// Up // Up
for (int k = delta - d; k <= delta + d; k += 2) { for (int k = delta - d; k <= delta + d; k += 2) {
// First step // First step
@@ -163,7 +161,6 @@ public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
} else { } else {
data.vUp[i] = data.vUp[i - 1]; data.vUp[i] = data.vUp[i - 1];
} }
int x = data.vUp[i] - 1; int x = data.vUp[i] - 1;
int y = x - start1 + start2 - k; int y = x - start1 + start2 - k;
while (x >= start1 && y >= start2 && equalizer.test(data.source.get(x), data.target.get(y))) { while (x >= start1 && y >= start2 && equalizer.test(data.source.get(x), data.target.get(y))) {
@@ -178,11 +175,9 @@ public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
} }
} }
} }
// According to Myers, this cannot happen // According to Myers, this cannot happen
throw new IllegalStateException("could not find a diff path"); 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) { private Snake buildSnake(DiffData data, final int start, final int diag, final int end1, final int end2) {
int end = start; int end = start;
while (end - diag < end2 && end < end1 && equalizer.test(data.source.get(end), data.target.get(end - diag))) { while (end - diag < end2 && end < end1 && equalizer.test(data.source.get(end), data.target.get(end - diag))) {
@@ -190,16 +185,13 @@ public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
} }
return new Snake(start, end, diag); return new Snake(start, end, diag);
} }
private class DiffData { private class DiffData {
final int size; final int size;
final int[] vDown; final int[] vDown;
final int[] vUp; final int[] vUp;
final List<Change> script; final List<Change> script;
final List<T> source; final List<T> source;
final List<T> target; final List<T> target;
public DiffData(List<T> source, List<T> target) { public DiffData(List<T> source, List<T> target) {
this.source = source; this.source = source;
this.target = target; this.target = target;
@@ -209,36 +201,14 @@ public class MyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
script = new ArrayList<>(); script = new ArrayList<>();
} }
} }
private class Snake { private class Snake {
final int start; final int start;
final int end; final int end;
final int diag; final int diag;
public 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.start = start;
this.end = end; this.end = end;
this.diag = diag; 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);
}
};
}
} }

View File

@@ -14,14 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.algorithm.myers; package com.github.difflib.algorithm.myers;
/** /**
* A node in a diffpath. * A node in a diffpath.
* *
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a> * @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
*/ */
public final class PathNode { public final class PathNode {
/** /**
* Position in the original sequence. * Position in the original sequence.
*/ */
@@ -34,11 +32,8 @@ public final class PathNode {
* The previous node in the path. * The previous node in the path.
*/ */
public final PathNode prev; public final PathNode prev;
public final boolean snake; public final boolean snake;
public final boolean bootstrap; public final boolean bootstrap;
/** /**
* Concatenates a new path node with an existing diffpath. * Concatenates a new path node with an existing diffpath.
* *
@@ -57,11 +52,9 @@ public final class PathNode {
} }
this.snake = snake; this.snake = snake;
} }
public boolean isSnake() { public boolean isSnake() {
return snake; return snake;
} }
/** /**
* Is this a bootstrap node? * Is this a bootstrap node?
* <p> * <p>
@@ -72,7 +65,6 @@ public final class PathNode {
public boolean isBootstrap() { public boolean isBootstrap() {
return bootstrap; return bootstrap;
} }
/** /**
* Skips sequences of {@link PathNode PathNodes} until a snake or bootstrap node is found, or the end of the * Skips sequences of {@link PathNode PathNodes} until a snake or bootstrap node is found, or the end of the
* path is reached. * path is reached.
@@ -88,7 +80,6 @@ public final class PathNode {
} }
return this; return this;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@@ -14,20 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* Abstract delta between a source and a target. * Abstract delta between a source and a target.
*
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public abstract class AbstractDelta<T> implements Serializable { public abstract class AbstractDelta<T> implements Serializable {
private final Chunk<T> source; private final Chunk<T> source;
private final Chunk<T> target; private final Chunk<T> target;
private final DeltaType type; private final DeltaType type;
public AbstractDelta(DeltaType type, Chunk<T> source, Chunk<T> target) { public AbstractDelta(DeltaType type, Chunk<T> source, Chunk<T> target) {
Objects.requireNonNull(source); Objects.requireNonNull(source);
Objects.requireNonNull(target); Objects.requireNonNull(target);
@@ -36,28 +34,24 @@ public abstract class AbstractDelta<T> implements Serializable {
this.source = source; this.source = source;
this.target = target; this.target = target;
} }
public Chunk<T> getSource() { public Chunk<T> getSource() {
return source; return source;
} }
public Chunk<T> getTarget() { public Chunk<T> getTarget() {
return target; return target;
} }
public DeltaType getType() { public DeltaType getType() {
return type; return type;
} }
/** /**
* Verify the chunk of this delta, to fit the target. * Verify the chunk of this delta, to fit the target.
*
* @param target * @param target
* @throws PatchFailedException * @throws PatchFailedException
*/ */
protected VerifyChunk verifyChunkToFitTarget(List<T> target) throws PatchFailedException { protected VerifyChunk verifyChunkToFitTarget(List<T> target) throws PatchFailedException {
return getSource().verifyChunk(target); return getSource().verifyChunk(target);
} }
protected VerifyChunk verifyAndApplyTo(List<T> target) throws PatchFailedException { protected VerifyChunk verifyAndApplyTo(List<T> target) throws PatchFailedException {
final VerifyChunk verify = verifyChunkToFitTarget(target); final VerifyChunk verify = verifyChunkToFitTarget(target);
if (verify == VerifyChunk.OK) { if (verify == VerifyChunk.OK) {
@@ -65,11 +59,8 @@ public abstract class AbstractDelta<T> implements Serializable {
} }
return verify; return verify;
} }
protected abstract void applyTo(List<T> target) throws PatchFailedException; protected abstract void applyTo(List<T> target) throws PatchFailedException;
protected abstract void restore(List<T> target); protected abstract void restore(List<T> target);
/** /**
* Apply patch fuzzy. * Apply patch fuzzy.
* *
@@ -82,17 +73,14 @@ public abstract class AbstractDelta<T> implements Serializable {
protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException { protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException {
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not supports applying patch fuzzy"); throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not supports applying patch fuzzy");
} }
/** /**
* Create a new delta of the actual instance with customized chunk data. * Create a new delta of the actual instance with customized chunk data.
*/ */
public abstract AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised); public abstract AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised);
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(this.source, this.target, this.type); return Objects.hash(this.source, this.target, this.type);
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {

View File

@@ -14,18 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* Describes the change-delta between original and revised texts. * Describes the change-delta between original and revised texts.
* *
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
* @param <T> The type of the compared elements in the data 'lines'. * @param <T> The type of the compared elements in the data 'lines'.
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/ */
public final class ChangeDelta<T> extends AbstractDelta<T> { public final class ChangeDelta<T> extends AbstractDelta<T> {
/** /**
* Creates a change delta with the two given chunks. * Creates a change delta with the two given chunks.
* *
@@ -37,7 +34,6 @@ public final class ChangeDelta<T> extends AbstractDelta<T> {
Objects.requireNonNull(source, "source must not be null"); Objects.requireNonNull(source, "source must not be null");
Objects.requireNonNull(target, "target must not be null"); Objects.requireNonNull(target, "target must not be null");
} }
@Override @Override
protected void applyTo(List<T> target) throws PatchFailedException { protected void applyTo(List<T> target) throws PatchFailedException {
int position = getSource().getPosition(); int position = getSource().getPosition();
@@ -51,7 +47,6 @@ public final class ChangeDelta<T> extends AbstractDelta<T> {
i++; i++;
} }
} }
@Override @Override
protected void restore(List<T> target) { protected void restore(List<T> target) {
int position = getTarget().getPosition(); int position = getTarget().getPosition();
@@ -65,26 +60,22 @@ public final class ChangeDelta<T> extends AbstractDelta<T> {
i++; i++;
} }
} }
protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException { protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException {
int size = getSource().size(); int size = getSource().size();
for (int i = fuzz; i < size - fuzz; i++) { for (int i = fuzz; i < size - fuzz; i++) {
target.remove(position + fuzz); target.remove(position + fuzz);
} }
int i = fuzz; int i = fuzz;
for (T line : getTarget().getLines().subList(fuzz, getTarget().size() - fuzz)) { for (T line : getTarget().getLines().subList(fuzz, getTarget().size() - fuzz)) {
target.add(position + i, line); target.add(position + i, line);
i++; i++;
} }
} }
@Override @Override
public String toString() { public String toString() {
return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: " return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: "
+ getSource().getLines() + " to " + getTarget().getLines() + "]"; + getSource().getLines() + " to " + getTarget().getLines() + "]";
} }
@Override @Override
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) { public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
return new ChangeDelta<T>(original, revised); return new ChangeDelta<T>(original, revised);

View File

@@ -14,13 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* Holds the information about the part of text involved in the diff process * Holds the information about the part of text involved in the diff process
* *
@@ -32,15 +30,13 @@ import java.util.Objects;
* differencing using this library. * differencing using this library.
* </p> * </p>
* *
* @author <a href="dm.naumenko@gmail.com>Dmitry Naumenko</a>
* @param <T> The type of the compared elements in the 'lines'. * @param <T> The type of the compared elements in the 'lines'.
* @author <a href="dm.naumenko@gmail.com>Dmitry Naumenko</a>
*/ */
public final class Chunk<T> implements Serializable { public final class Chunk<T> implements Serializable {
private final int position; private final int position;
private List<T> lines;
private final List<Integer> changePosition; private final List<Integer> changePosition;
private List<T> lines;
/** /**
* Creates a chunk and saves a copy of affected lines * Creates a chunk and saves a copy of affected lines
* *
@@ -53,7 +49,6 @@ public final class Chunk<T> implements Serializable {
this.lines = new ArrayList<>(lines); this.lines = new ArrayList<>(lines);
this.changePosition = changePosition != null ? new ArrayList<>(changePosition) : null; this.changePosition = changePosition != null ? new ArrayList<>(changePosition) : null;
} }
/** /**
* Creates a chunk and saves a copy of affected lines * Creates a chunk and saves a copy of affected lines
* *
@@ -63,7 +58,6 @@ public final class Chunk<T> implements Serializable {
public Chunk(int position, List<T> lines) { public Chunk(int position, List<T> lines) {
this(position, lines, null); this(position, lines, null);
} }
/** /**
* Creates a chunk and saves a copy of affected lines * Creates a chunk and saves a copy of affected lines
* *
@@ -76,7 +70,6 @@ public final class Chunk<T> implements Serializable {
this.lines = Arrays.asList(lines); this.lines = Arrays.asList(lines);
this.changePosition = changePosition != null ? new ArrayList<>(changePosition) : null; this.changePosition = changePosition != null ? new ArrayList<>(changePosition) : null;
} }
/** /**
* Creates a chunk and saves a copy of affected lines * Creates a chunk and saves a copy of affected lines
* *
@@ -86,7 +79,6 @@ public final class Chunk<T> implements Serializable {
public Chunk(int position, T[] lines) { public Chunk(int position, T[] lines) {
this(position, lines, null); this(position, lines, null);
} }
/** /**
* Verifies that this chunk's saved text matches the corresponding text in * Verifies that this chunk's saved text matches the corresponding text in
* the given sequence. * the given sequence.
@@ -97,7 +89,6 @@ public final class Chunk<T> implements Serializable {
public VerifyChunk verifyChunk(List<T> target) throws PatchFailedException { public VerifyChunk verifyChunk(List<T> target) throws PatchFailedException {
return verifyChunk(target, 0, getPosition()); return verifyChunk(target, 0, getPosition());
} }
/** /**
* Verifies that this chunk's saved text matches the corresponding text in * Verifies that this chunk's saved text matches the corresponding text in
* the given sequence. * the given sequence.
@@ -112,7 +103,6 @@ public final class Chunk<T> implements Serializable {
int startIndex = fuzz; int startIndex = fuzz;
int lastIndex = size() - fuzz; int lastIndex = size() - fuzz;
int last = position + size() - 1; int last = position + size() - 1;
if (position + fuzz > target.size() || last - fuzz > target.size()) { if (position + fuzz > target.size() || last - fuzz > target.size()) {
return VerifyChunk.POSITION_OUT_OF_TARGET; return VerifyChunk.POSITION_OUT_OF_TARGET;
} }
@@ -123,48 +113,40 @@ public final class Chunk<T> implements Serializable {
} }
return VerifyChunk.OK; return VerifyChunk.OK;
} }
/** /**
* @return the start position of chunk in the text * @return the start position of chunk in the text
*/ */
public int getPosition() { public int getPosition() {
return position; return position;
} }
public void setLines(List<T> lines) {
this.lines = lines;
}
/** /**
* @return the affected lines * @return the affected lines
*/ */
public List<T> getLines() { public List<T> getLines() {
return lines; return lines;
} }
public void setLines(List<T> lines) {
this.lines = lines;
}
/** /**
* @return the positions of changed lines of chunk in the text * @return the positions of changed lines of chunk in the text
*/ */
public List<Integer> getChangePosition() { public List<Integer> getChangePosition() {
return changePosition; return changePosition;
} }
public int size() { public int size() {
return lines.size(); return lines.size();
} }
/** /**
* Returns the index of the last line of the chunk. * Returns the index of the last line of the chunk.
*/ */
public int last() { public int last() {
return getPosition() + size() - 1; return getPosition() + size() - 1;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(lines, position, size()); return Objects.hash(lines, position, size());
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
@@ -186,10 +168,8 @@ public final class Chunk<T> implements Serializable {
} }
return position == other.position; return position == other.position;
} }
@Override @Override
public String toString() { public String toString() {
return "[position: " + position + ", size: " + size() + ", lines: " + lines + "]"; return "[position: " + position + ", size: " + size() + ", lines: " + lines + "]";
} }
} }

View File

@@ -18,16 +18,12 @@ limitations under the License.
* #L% * #L%
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
/** /**
*
* @author tw * @author tw
*/ */
@FunctionalInterface @FunctionalInterface
public interface ConflictOutput<T> extends Serializable { public interface ConflictOutput<T> extends Serializable {
public void processConflict(VerifyChunk verifyChunk, AbstractDelta<T> delta, List<T> result) throws PatchFailedException; public void processConflict(VerifyChunk verifyChunk, AbstractDelta<T> delta, List<T> result) throws PatchFailedException;
} }

View File

@@ -14,17 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.util.List; import java.util.List;
/** /**
* Describes the delete-delta between original and revised texts. * Describes the delete-delta between original and revised texts.
* *
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
* @param <T> The type of the compared elements in the 'lines'. * @param <T> The type of the compared elements in the 'lines'.
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/ */
public final class DeleteDelta<T> extends AbstractDelta<T> { public final class DeleteDelta<T> extends AbstractDelta<T> {
/** /**
* Creates a change delta with the two given chunks. * Creates a change delta with the two given chunks.
* *
@@ -34,7 +31,6 @@ public final class DeleteDelta<T> extends AbstractDelta<T> {
public DeleteDelta(Chunk<T> original, Chunk<T> revised) { public DeleteDelta(Chunk<T> original, Chunk<T> revised) {
super(DeltaType.DELETE, original, revised); super(DeltaType.DELETE, original, revised);
} }
@Override @Override
protected void applyTo(List<T> target) throws PatchFailedException { protected void applyTo(List<T> target) throws PatchFailedException {
int position = getSource().getPosition(); int position = getSource().getPosition();
@@ -43,7 +39,6 @@ public final class DeleteDelta<T> extends AbstractDelta<T> {
target.remove(position); target.remove(position);
} }
} }
@Override @Override
protected void restore(List<T> target) { protected void restore(List<T> target) {
int position = this.getTarget().getPosition(); int position = this.getTarget().getPosition();
@@ -52,13 +47,11 @@ public final class DeleteDelta<T> extends AbstractDelta<T> {
target.add(position + i, lines.get(i)); target.add(position + i, lines.get(i));
} }
} }
@Override @Override
public String toString() { public String toString() {
return "[DeleteDelta, position: " + getSource().getPosition() + ", lines: " return "[DeleteDelta, position: " + getSource().getPosition() + ", lines: "
+ getSource().getLines() + "]"; + getSource().getLines() + "]";
} }
@Override @Override
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) { public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
return new DeleteDelta<T>(original, revised); return new DeleteDelta<T>(original, revised);

View File

@@ -14,21 +14,19 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
/** /**
* Specifies the type of the delta. There are three types of modifications from * Specifies the type of the delta. There are three types of modifications from
* the original to get the revised text. * the original to get the revised text.
* * <p>
* CHANGE: a block of data of the original is replaced by another block of data. * CHANGE: a block of data of the original is replaced by another block of data.
* DELETE: a block of data of the original is removed * DELETE: a block of data of the original is removed
* INSERT: at a position of the original a block of data is inserted * INSERT: at a position of the original a block of data is inserted
* * <p>
* to be complete there is also * to be complete there is also
* * <p>
* EQUAL: a block of data of original and the revised text is equal * EQUAL: a block of data of original and the revised text is equal
* * <p>
* which is no change at all. * which is no change at all.
*
*/ */
public enum DeltaType { public enum DeltaType {
/** /**

View File

@@ -14,19 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
/** /**
* Base class for all exceptions emanating from this package. * Base class for all exceptions emanating from this package.
* *
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a> * @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
*/ */
public class DiffException extends Exception { public class DiffException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public DiffException() { public DiffException() {
} }
public DiffException(String msg) { public DiffException(String msg) {
super(msg); super(msg);
} }

View File

@@ -14,27 +14,22 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.util.List; import java.util.List;
/** /**
* This delta contains equal lines of data. Therefore nothing is to do in applyTo and restore. * This delta contains equal lines of data. Therefore nothing is to do in applyTo and restore.
*
* @author tobens * @author tobens
*/ */
public class EqualDelta<T> extends AbstractDelta<T> { public class EqualDelta<T> extends AbstractDelta<T> {
public EqualDelta(Chunk<T> source, Chunk<T> target) { public EqualDelta(Chunk<T> source, Chunk<T> target) {
super(DeltaType.EQUAL, source, target); super(DeltaType.EQUAL, source, target);
} }
@Override @Override
protected void applyTo(List<T> target) throws PatchFailedException { protected void applyTo(List<T> target) throws PatchFailedException {
} }
@Override @Override
protected void restore(List<T> target) { protected void restore(List<T> target) {
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -42,13 +37,11 @@ public class EqualDelta<T> extends AbstractDelta<T> {
protected void applyFuzzyToAt(List<T> target, int fuzz, int delta) { protected void applyFuzzyToAt(List<T> target, int fuzz, int delta) {
// equals so no operations // equals so no operations
} }
@Override @Override
public String toString() { public String toString() {
return "[EqualDelta, position: " + getSource().getPosition() + ", lines: " return "[EqualDelta, position: " + getSource().getPosition() + ", lines: "
+ getSource().getLines() + "]"; + getSource().getLines() + "]";
} }
@Override @Override
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) { public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
return new EqualDelta<T>(original, revised); return new EqualDelta<T>(original, revised);

View File

@@ -14,17 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import java.util.List; import java.util.List;
/** /**
* Describes the add-delta between original and revised texts. * Describes the add-delta between original and revised texts.
* *
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
* @param <T> The type of the compared elements in the 'lines'. * @param <T> The type of the compared elements in the 'lines'.
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/ */
public final class InsertDelta<T> extends AbstractDelta<T> { public final class InsertDelta<T> extends AbstractDelta<T> {
/** /**
* Creates an insert delta with the two given chunks. * Creates an insert delta with the two given chunks.
* *
@@ -34,7 +31,6 @@ public final class InsertDelta<T> extends AbstractDelta<T> {
public InsertDelta(Chunk<T> original, Chunk<T> revised) { public InsertDelta(Chunk<T> original, Chunk<T> revised) {
super(DeltaType.INSERT, original, revised); super(DeltaType.INSERT, original, revised);
} }
@Override @Override
protected void applyTo(List<T> target) throws PatchFailedException { protected void applyTo(List<T> target) throws PatchFailedException {
int position = this.getSource().getPosition(); int position = this.getSource().getPosition();
@@ -43,7 +39,6 @@ public final class InsertDelta<T> extends AbstractDelta<T> {
target.add(position + i, lines.get(i)); target.add(position + i, lines.get(i));
} }
} }
@Override @Override
protected void restore(List<T> target) { protected void restore(List<T> target) {
int position = getTarget().getPosition(); int position = getTarget().getPosition();
@@ -52,13 +47,11 @@ public final class InsertDelta<T> extends AbstractDelta<T> {
target.remove(position); target.remove(position);
} }
} }
@Override @Override
public String toString() { public String toString() {
return "[InsertDelta, position: " + getSource().getPosition() return "[InsertDelta, position: " + getSource().getPosition()
+ ", lines: " + getTarget().getLines() + "]"; + ", lines: " + getTarget().getLines() + "]";
} }
@Override @Override
public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) { public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
return new InsertDelta<T>(original, revised); return new InsertDelta<T>(original, revised);

View File

@@ -18,8 +18,6 @@ limitations under the License.
* #L% * #L%
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
import static java.util.Comparator.comparing;
import com.github.difflib.algorithm.Change; import com.github.difflib.algorithm.Change;
import java.io.Serializable; import java.io.Serializable;
@@ -28,25 +26,93 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import static java.util.Comparator.comparing;
/** /**
* Describes the patch holding all deltas between the original and revised * Describes the patch holding all deltas between the original and revised
* texts. * texts.
* *
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
* @param <T> The type of the compared elements in the 'lines'. * @param <T> The type of the compared elements in the 'lines'.
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/ */
public final class Patch<T> implements Serializable { public final class Patch<T> implements Serializable {
/**
* Git like merge conflict output.
*/
public static final ConflictOutput<String> CONFLICT_PRODUCES_MERGE_CONFLICT = (VerifyChunk verifyChunk, AbstractDelta<String> delta, List<String> result) -> {
if (result.size() > delta.getSource().getPosition()) {
List<String> orgData = new ArrayList<>();
for (int i = 0; i < delta.getSource().size(); i++) {
orgData.add(result.get(delta.getSource().getPosition()));
result.remove(delta.getSource().getPosition());
}
orgData.add(0, "<<<<<< HEAD");
orgData.add("======");
orgData.addAll(delta.getSource().getLines());
orgData.add(">>>>>>> PATCH");
result.addAll(delta.getSource().getPosition(), orgData);
} else {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
};
/**
* Standard Patch behaviour to throw an exception for pathching conflicts.
*/
public final ConflictOutput<T> CONFLICT_PRODUCES_EXCEPTION = (VerifyChunk verifyChunk, AbstractDelta<T> delta, List<T> result) -> {
throw new PatchFailedException("could not apply patch due to " + verifyChunk.toString());
};
private final List<AbstractDelta<T>> deltas; private final List<AbstractDelta<T>> deltas;
private ConflictOutput<T> conflictOutput = CONFLICT_PRODUCES_EXCEPTION;
public Patch() { public Patch() {
this(10); this(10);
} }
public Patch(int estimatedPatchSize) { public Patch(int estimatedPatchSize) {
deltas = new ArrayList<>(estimatedPatchSize); deltas = new ArrayList<>(estimatedPatchSize);
} }
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> changes) {
return generate(original, revised, changes, false);
}
private static <T> Chunk<T> buildChunk(int start, int end, List<T> data) {
return new Chunk<>(start, new ArrayList<>(data.subList(start, end)));
}
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> _changes, boolean includeEquals) {
Patch<T> patch = new Patch<>(_changes.size());
int startOriginal = 0;
int startRevised = 0;
List<Change> changes = _changes;
if (includeEquals) {
changes = new ArrayList<Change>(_changes);
Collections.sort(changes, comparing(d -> d.startOriginal));
}
for (Change change : changes) {
if (includeEquals && startOriginal < change.startOriginal) {
patch.addDelta(new EqualDelta<T>(
buildChunk(startOriginal, change.startOriginal, original),
buildChunk(startRevised, change.startRevised, revised)));
}
Chunk<T> orgChunk = buildChunk(change.startOriginal, change.endOriginal, original);
Chunk<T> revChunk = buildChunk(change.startRevised, change.endRevised, revised);
switch (change.deltaType) {
case DELETE:
patch.addDelta(new DeleteDelta<>(orgChunk, revChunk));
break;
case INSERT:
patch.addDelta(new InsertDelta<>(orgChunk, revChunk));
break;
case CHANGE:
patch.addDelta(new ChangeDelta<>(orgChunk, revChunk));
break;
default:
}
startOriginal = change.endOriginal;
startRevised = change.endRevised;
}
if (includeEquals && startOriginal < original.size()) {
patch.addDelta(new EqualDelta<T>(
buildChunk(startOriginal, original.size(), original),
buildChunk(startRevised, revised.size(), revised)));
}
return patch;
}
/** /**
* Creates a new list, the patch is being applied to. * Creates a new list, the patch is being applied to.
* *
@@ -59,7 +125,6 @@ public final class Patch<T> implements Serializable {
applyToExisting(result); applyToExisting(result);
return result; return result;
} }
/** /**
* Applies the patch to the supplied list. * Applies the patch to the supplied list.
* *
@@ -78,33 +143,10 @@ public final class Patch<T> implements Serializable {
} }
} }
} }
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 { public List<T> applyFuzzy(List<T> target, int maxFuzz) throws PatchFailedException {
PatchApplyingContext<T> ctx = new PatchApplyingContext<>(new ArrayList<>(target), maxFuzz); PatchApplyingContext<T> ctx = new PatchApplyingContext<>(new ArrayList<>(target), maxFuzz);
// the difference between patch's position and actually applied position // the difference between patch's position and actually applied position
int lastPatchDelta = 0; int lastPatchDelta = 0;
for (AbstractDelta<T> delta : getDeltas()) { for (AbstractDelta<T> delta : getDeltas()) {
ctx.defaultPosition = delta.getSource().getPosition() + lastPatchDelta; ctx.defaultPosition = delta.getSource().getPosition() + lastPatchDelta;
int patchPosition = findPositionFuzzy(ctx, delta); int patchPosition = findPositionFuzzy(ctx, delta);
@@ -116,10 +158,8 @@ public final class Patch<T> implements Serializable {
conflictOutput.processConflict(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET, delta, ctx.result); conflictOutput.processConflict(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET, delta, ctx.result);
} }
} }
return ctx.result; return ctx.result;
} }
// negative for not found // negative for not found
private int findPositionFuzzy(PatchApplyingContext<T> ctx, AbstractDelta<T> delta) throws PatchFailedException { private int findPositionFuzzy(PatchApplyingContext<T> ctx, AbstractDelta<T> delta) throws PatchFailedException {
for (int fuzz = 0; fuzz <= ctx.maxFuzz; fuzz++) { for (int fuzz = 0; fuzz <= ctx.maxFuzz; fuzz++) {
@@ -131,16 +171,13 @@ public final class Patch<T> implements Serializable {
} }
return -1; return -1;
} }
// negative for not found // negative for not found
private int findPositionWithFuzz(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz) throws PatchFailedException { private int findPositionWithFuzz(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz) throws PatchFailedException {
if (delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition) == VerifyChunk.OK) { if (delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition) == VerifyChunk.OK) {
return ctx.defaultPosition; return ctx.defaultPosition;
} }
ctx.beforeOutRange = false; ctx.beforeOutRange = false;
ctx.afterOutRange = false; ctx.afterOutRange = false;
// moreDelta >= 0: just for overflow guard, not a normal condition // moreDelta >= 0: just for overflow guard, not a normal condition
//noinspection OverflowingLoopIndex //noinspection OverflowingLoopIndex
for (int moreDelta = 0; moreDelta >= 0; moreDelta++) { for (int moreDelta = 0; moreDelta >= 0; moreDelta++) {
@@ -152,10 +189,8 @@ public final class Patch<T> implements Serializable {
break; break;
} }
} }
return -1; return -1;
} }
// negative for not found // negative for not found
private int findPositionWithFuzzAndMoreDelta(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz, int moreDelta) throws PatchFailedException { 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 // range check: can't apply before end of last patch
@@ -174,7 +209,6 @@ public final class Patch<T> implements Serializable {
ctx.afterOutRange = true; ctx.afterOutRange = true;
} }
} }
if (!ctx.beforeOutRange) { if (!ctx.beforeOutRange) {
VerifyChunk before = delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition - moreDelta); VerifyChunk before = delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition - moreDelta);
if (before == VerifyChunk.OK) { if (before == VerifyChunk.OK) {
@@ -189,40 +223,6 @@ public final class Patch<T> implements Serializable {
} }
return -1; return -1;
} }
/**
* Standard Patch behaviour to throw an exception for pathching conflicts.
*/
public final ConflictOutput<T> CONFLICT_PRODUCES_EXCEPTION = (VerifyChunk verifyChunk, AbstractDelta<T> delta, List<T> result) -> {
throw new PatchFailedException("could not apply patch due to " + verifyChunk.toString());
};
/**
* Git like merge conflict output.
*/
public static final ConflictOutput<String> CONFLICT_PRODUCES_MERGE_CONFLICT = (VerifyChunk verifyChunk, AbstractDelta<String> delta, List<String> result) -> {
if (result.size() > delta.getSource().getPosition()) {
List<String> orgData = new ArrayList<>();
for (int i = 0; i < delta.getSource().size(); i++) {
orgData.add(result.get(delta.getSource().getPosition()));
result.remove(delta.getSource().getPosition());
}
orgData.add(0, "<<<<<< HEAD");
orgData.add("======");
orgData.addAll(delta.getSource().getLines());
orgData.add(">>>>>>> PATCH");
result.addAll(delta.getSource().getPosition(), orgData);
} else {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
};
private ConflictOutput<T> conflictOutput = CONFLICT_PRODUCES_EXCEPTION;
/** /**
* Alter normal conflict output behaviour to e.g. inclide some conflict * Alter normal conflict output behaviour to e.g. inclide some conflict
* statements in the result, like git does it. * statements in the result, like git does it.
@@ -231,7 +231,6 @@ public final class Patch<T> implements Serializable {
this.conflictOutput = conflictOutput; this.conflictOutput = conflictOutput;
return this; return this;
} }
/** /**
* Creates a new list, containing the restored state of the given list. * Creates a new list, containing the restored state of the given list.
* Opposite to {@link #applyTo(List)} method. * Opposite to {@link #applyTo(List)} method.
@@ -244,8 +243,6 @@ public final class Patch<T> implements Serializable {
restoreToExisting(result); restoreToExisting(result);
return result; return result;
} }
/** /**
* Restores all changes within the given list. * Restores all changes within the given list.
* Opposite to {@link #applyToExisting(List)} method. * Opposite to {@link #applyToExisting(List)} method.
@@ -261,7 +258,6 @@ public final class Patch<T> implements Serializable {
delta.restore(target); delta.restore(target);
} }
} }
/** /**
* Add the given delta to this patch * Add the given delta to this patch
* *
@@ -270,7 +266,6 @@ public final class Patch<T> implements Serializable {
public void addDelta(AbstractDelta<T> delta) { public void addDelta(AbstractDelta<T> delta) {
deltas.add(delta); deltas.add(delta);
} }
/** /**
* Get the list of computed deltas * Get the list of computed deltas
* *
@@ -280,65 +275,23 @@ public final class Patch<T> implements Serializable {
deltas.sort(comparing(d -> d.getSource().getPosition())); deltas.sort(comparing(d -> d.getSource().getPosition()));
return deltas; return deltas;
} }
@Override @Override
public String toString() { public String toString() {
return "Patch{" + "deltas=" + deltas + '}'; return "Patch{" + "deltas=" + deltas + '}';
} }
private static class PatchApplyingContext<T> {
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> changes) { public final List<T> result;
return generate(original, revised, changes, false); public final int maxFuzz;
} // the position last patch applied to.
public int lastPatchEnd = -1;
private static <T> Chunk<T> buildChunk(int start, int end, List<T> data) { ///// passing values from find to apply
return new Chunk<>(start, new ArrayList<>(data.subList(start, end))); public int currentFuzz = 0;
} public int defaultPosition;
public boolean beforeOutRange = false;
public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> _changes, boolean includeEquals) { public boolean afterOutRange = false;
Patch<T> patch = new Patch<>(_changes.size()); private PatchApplyingContext(List<T> result, int maxFuzz) {
int startOriginal = 0; this.result = result;
int startRevised = 0; this.maxFuzz = maxFuzz;
}
List<Change> changes = _changes;
if (includeEquals) {
changes = new ArrayList<Change>(_changes);
Collections.sort(changes, comparing(d -> d.startOriginal));
}
for (Change change : changes) {
if (includeEquals && startOriginal < change.startOriginal) {
patch.addDelta(new EqualDelta<T>(
buildChunk(startOriginal, change.startOriginal, original),
buildChunk(startRevised, change.startRevised, revised)));
}
Chunk<T> orgChunk = buildChunk(change.startOriginal, change.endOriginal, original);
Chunk<T> revChunk = buildChunk(change.startRevised, change.endRevised, revised);
switch (change.deltaType) {
case DELETE:
patch.addDelta(new DeleteDelta<>(orgChunk, revChunk));
break;
case INSERT:
patch.addDelta(new InsertDelta<>(orgChunk, revChunk));
break;
case CHANGE:
patch.addDelta(new ChangeDelta<>(orgChunk, revChunk));
break;
default:
}
startOriginal = change.endOriginal;
startRevised = change.endRevised;
}
if (includeEquals && startOriginal < original.size()) {
patch.addDelta(new EqualDelta<T>(
buildChunk(startOriginal, original.size(), original),
buildChunk(startRevised, revised.size(), revised)));
}
return patch;
} }
} }

View File

@@ -14,19 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
/** /**
* Thrown whenever a delta cannot be applied as a patch to a given text. * Thrown whenever a delta cannot be applied as a patch to a given text.
* *
* @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a> * @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
*/ */
public class PatchFailedException extends DiffException { public class PatchFailedException extends DiffException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public PatchFailedException() { public PatchFailedException() {
} }
public PatchFailedException(String msg) { public PatchFailedException(String msg) {
super(msg); super(msg);
} }

View File

@@ -14,9 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.patch; package com.github.difflib.patch;
/** /**
*
* @author tw * @author tw
*/ */
public enum VerifyChunk { public enum VerifyChunk {

View File

@@ -14,64 +14,50 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.text; package com.github.difflib.text;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
/** /**
* Describes the diff row in form [tag, oldLine, newLine) for showing the difference between two texts * Describes the diff row in form [tag, oldLine, newLine) for showing the difference between two texts
* *
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a> * @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/ */
public final class DiffRow implements Serializable { public final class DiffRow implements Serializable {
private Tag tag;
private final String oldLine; private final String oldLine;
private final String newLine; private final String newLine;
private Tag tag;
public DiffRow(Tag tag, String oldLine, String newLine) { public DiffRow(Tag tag, String oldLine, String newLine) {
this.tag = tag; this.tag = tag;
this.oldLine = oldLine; this.oldLine = oldLine;
this.newLine = newLine; this.newLine = newLine;
} }
public enum Tag {
INSERT, DELETE, CHANGE, EQUAL
}
/** /**
* @return the tag * @return the tag
*/ */
public Tag getTag() { public Tag getTag() {
return tag; return tag;
} }
/** /**
* @param tag the tag to set * @param tag the tag to set
*/ */
public void setTag(Tag tag) { public void setTag(Tag tag) {
this.tag = tag; this.tag = tag;
} }
/** /**
* @return the oldLine * @return the oldLine
*/ */
public String getOldLine() { public String getOldLine() {
return oldLine; return oldLine;
} }
/** /**
* @return the newLine * @return the newLine
*/ */
public String getNewLine() { public String getNewLine() {
return newLine; return newLine;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(newLine, oldLine, tag); return Objects.hash(newLine, oldLine, tag);
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
@@ -107,9 +93,11 @@ public final class DiffRow implements Serializable {
} }
return true; return true;
} }
@Override @Override
public String toString() { public String toString() {
return "[" + this.tag + "," + this.oldLine + "," + this.newLine + "]"; return "[" + this.tag + "," + this.oldLine + "," + this.newLine + "]";
} }
public enum Tag {
INSERT, DELETE, CHANGE, EQUAL
}
} }

View File

@@ -14,35 +14,29 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.text; package com.github.difflib.text;
import com.github.difflib.DiffUtils; import com.github.difflib.DiffUtils;
import com.github.difflib.patch.AbstractDelta; import com.github.difflib.patch.*;
import com.github.difflib.patch.ChangeDelta;
import com.github.difflib.patch.Chunk;
import com.github.difflib.patch.DeleteDelta;
import com.github.difflib.patch.DeltaType;
import com.github.difflib.patch.InsertDelta;
import com.github.difflib.patch.Patch;
import com.github.difflib.text.DiffRow.Tag; import com.github.difflib.text.DiffRow.Tag;
import com.github.difflib.text.deltamerge.DeltaMergeUtils; import com.github.difflib.text.deltamerge.DeltaMergeUtils;
import com.github.difflib.text.deltamerge.InlineDeltaMergeInfo; import com.github.difflib.text.deltamerge.InlineDeltaMergeInfo;
import java.util.*; import java.util.*;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toList;
/** /**
* This class for generating DiffRows for side-by-sidy view. You can customize * This class for generating DiffRows for side-by-sidy view. You can customize
* the way of generating. For example, show inline diffs on not, ignoring white * the way of generating. For example, show inline diffs on not, ignoring white
* spaces or/and blank lines and so on. All parameters for generating are * spaces or/and blank lines and so on. All parameters for generating are
* optional. If you do not specify them, the class will use the default values. * optional. If you do not specify them, the class will use the default values.
* * <p>
* These values are: showInlineDiffs = false; ignoreWhiteSpaces = true; * These values are: showInlineDiffs = false; ignoreWhiteSpaces = true;
* ignoreBlankLines = true; ... * ignoreBlankLines = true; ...
* * <p>
* For instantiating the DiffRowGenerator you should use the its builder. Like * For instantiating the DiffRowGenerator you should use the its builder. Like
* in example <code> * in example <code>
* DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true). * DiffRowGenerator generator = new DiffRowGenerator.Builder().showInlineDiffs(true).
@@ -50,14 +44,8 @@ import static java.util.stream.Collectors.toList;
* </code> * </code>
*/ */
public final class DiffRowGenerator { public final class DiffRowGenerator {
public static final BiPredicate<String, String> DEFAULT_EQUALIZER = Object::equals; public static final BiPredicate<String, String> DEFAULT_EQUALIZER = Object::equals;
public static final BiPredicate<String, String> IGNORE_WHITESPACE_EQUALIZER = (original, revised)
-> adjustWhitespace(original).equals(adjustWhitespace(revised));
public static final Function<String, String> LINE_NORMALIZER_FOR_HTML = StringUtils::normalize; public static final Function<String, String> LINE_NORMALIZER_FOR_HTML = StringUtils::normalize;
/** /**
* Splitting lines by character to achieve char by char diff checking. * Splitting lines by character to achieve char by char diff checking.
*/ */
@@ -68,31 +56,63 @@ public final class DiffRowGenerator {
} }
return list; 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. * Splitting lines by word to achieve word by word diff checking.
*/ */
public static final Function<String, List<String>> SPLITTER_BY_WORD = line -> splitStringPreserveDelimiter(line, SPLIT_BY_WORD_PATTERN); public static final Function<String, List<String>> SPLITTER_BY_WORD = line -> splitStringPreserveDelimiter(line, SPLIT_BY_WORD_PATTERN);
public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+"); public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
public static final BiPredicate<String, String> IGNORE_WHITESPACE_EQUALIZER = (original, revised)
-> adjustWhitespace(original).equals(adjustWhitespace(revised));
public static final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> DEFAULT_INLINE_DELTA_MERGER = InlineDeltaMergeInfo::getDeltas; public static final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> DEFAULT_INLINE_DELTA_MERGER = InlineDeltaMergeInfo::getDeltas;
/** /**
* Merge diffs which are separated by equalities consisting of whitespace only. * Merge diffs which are separated by equalities consisting of whitespace only.
*/ */
public static final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> WHITESPACE_EQUALITIES_MERGER = deltaMergeInfo -> DeltaMergeUtils public static final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> WHITESPACE_EQUALITIES_MERGER = deltaMergeInfo -> DeltaMergeUtils
.mergeInlineDeltas(deltaMergeInfo, equalities -> equalities.stream().allMatch(s -> s == null || s.replaceAll("\\s+", "").equals(""))); .mergeInlineDeltas(deltaMergeInfo, equalities -> equalities.stream().allMatch(s -> s == null || s.replaceAll("\\s+", "").equals("")));
private final int columnWidth;
private final BiPredicate<String, String> equalizer;
private final boolean ignoreWhiteSpaces;
private final Function<String, List<String>> inlineDiffSplitter;
private final boolean mergeOriginalRevised;
private final BiFunction<Tag, Boolean, String> newTag;
private final BiFunction<Tag, Boolean, String> oldTag;
private final boolean reportLinesUnchanged;
private final Function<String, String> lineNormalizer;
private final Function<String, String> processDiffs;
private final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger;
private final boolean showInlineDiffs;
private final boolean replaceOriginalLinefeedInChangesWithSpaces;
private final boolean decompressDeltas;
private DiffRowGenerator(Builder builder) {
showInlineDiffs = builder.showInlineDiffs;
ignoreWhiteSpaces = builder.ignoreWhiteSpaces;
oldTag = builder.oldTag;
newTag = builder.newTag;
columnWidth = builder.columnWidth;
mergeOriginalRevised = builder.mergeOriginalRevised;
inlineDiffSplitter = builder.inlineDiffSplitter;
decompressDeltas = builder.decompressDeltas;
if (builder.equalizer != null) {
equalizer = builder.equalizer;
} else {
equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER;
}
reportLinesUnchanged = builder.reportLinesUnchanged;
lineNormalizer = builder.lineNormalizer;
processDiffs = builder.processDiffs;
inlineDeltaMerger = builder.inlineDeltaMerger;
replaceOriginalLinefeedInChangesWithSpaces = builder.replaceOriginalLinefeedInChangesWithSpaces;
Objects.requireNonNull(inlineDiffSplitter);
Objects.requireNonNull(lineNormalizer);
Objects.requireNonNull(inlineDeltaMerger);
}
public static Builder create() { public static Builder create() {
return new Builder(); return new Builder();
} }
private static String adjustWhitespace(String raw) { private static String adjustWhitespace(String raw) {
return WHITESPACE_PATTERN.matcher(raw.trim()).replaceAll(" "); return WHITESPACE_PATTERN.matcher(raw.trim()).replaceAll(" ");
} }
protected final static List<String> splitStringPreserveDelimiter(String str, Pattern SPLIT_PATTERN) { protected final static List<String> splitStringPreserveDelimiter(String str, Pattern SPLIT_PATTERN) {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
if (str != null) { if (str != null) {
@@ -111,7 +131,6 @@ public final class DiffRowGenerator {
} }
return list; return list;
} }
/** /**
* Wrap the elements in the sequence with the given tag * Wrap the elements in the sequence with the given tag
* *
@@ -124,9 +143,7 @@ public final class DiffRowGenerator {
int endPosition, Tag tag, BiFunction<Tag, Boolean, String> tagGenerator, int endPosition, Tag tag, BiFunction<Tag, Boolean, String> tagGenerator,
Function<String, String> processDiffs, boolean replaceLinefeedWithSpace) { Function<String, String> processDiffs, boolean replaceLinefeedWithSpace) {
int endPos = endPosition; int endPos = endPosition;
while (endPos >= startPosition) { while (endPos >= startPosition) {
//search position for end tag //search position for end tag
while (endPos > startPosition) { while (endPos > startPosition) {
if (!"\n".equals(sequence.get(endPos - 1))) { if (!"\n".equals(sequence.get(endPos - 1))) {
@@ -137,18 +154,15 @@ public final class DiffRowGenerator {
} }
endPos--; endPos--;
} }
if (endPos == startPosition) { if (endPos == startPosition) {
break; break;
} }
sequence.add(endPos, tagGenerator.apply(tag, false)); sequence.add(endPos, tagGenerator.apply(tag, false));
if (processDiffs != null) { if (processDiffs != null) {
sequence.set(endPos - 1, sequence.set(endPos - 1,
processDiffs.apply(sequence.get(endPos - 1))); processDiffs.apply(sequence.get(endPos - 1)));
} }
endPos--; endPos--;
//search position for end tag //search position for end tag
while (endPos > startPosition) { while (endPos > startPosition) {
if ("\n".equals(sequence.get(endPos - 1))) { if ("\n".equals(sequence.get(endPos - 1))) {
@@ -164,56 +178,10 @@ public final class DiffRowGenerator {
} }
endPos--; endPos--;
} }
sequence.add(endPos, tagGenerator.apply(tag, true)); sequence.add(endPos, tagGenerator.apply(tag, true));
endPos--; endPos--;
} }
} }
private final int columnWidth;
private final BiPredicate<String, String> equalizer;
private final boolean ignoreWhiteSpaces;
private final Function<String, List<String>> inlineDiffSplitter;
private final boolean mergeOriginalRevised;
private final BiFunction<Tag, Boolean, String> newTag;
private final BiFunction<Tag, Boolean, String> oldTag;
private final boolean reportLinesUnchanged;
private final Function<String, String> lineNormalizer;
private final Function<String, String> processDiffs;
private final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger;
private final boolean showInlineDiffs;
private final boolean replaceOriginalLinefeedInChangesWithSpaces;
private final boolean decompressDeltas;
private DiffRowGenerator(Builder builder) {
showInlineDiffs = builder.showInlineDiffs;
ignoreWhiteSpaces = builder.ignoreWhiteSpaces;
oldTag = builder.oldTag;
newTag = builder.newTag;
columnWidth = builder.columnWidth;
mergeOriginalRevised = builder.mergeOriginalRevised;
inlineDiffSplitter = builder.inlineDiffSplitter;
decompressDeltas = builder.decompressDeltas;
if (builder.equalizer != null) {
equalizer = builder.equalizer;
} else {
equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER;
}
reportLinesUnchanged = builder.reportLinesUnchanged;
lineNormalizer = builder.lineNormalizer;
processDiffs = builder.processDiffs;
inlineDeltaMerger = builder.inlineDeltaMerger;
replaceOriginalLinefeedInChangesWithSpaces = builder.replaceOriginalLinefeedInChangesWithSpaces;
Objects.requireNonNull(inlineDiffSplitter);
Objects.requireNonNull(lineNormalizer);
Objects.requireNonNull(inlineDeltaMerger);
}
/** /**
* Get the DiffRows describing the difference between original and revised * Get the DiffRows describing the difference between original and revised
* texts using the given patch. Useful for displaying side-by-side diff. * texts using the given patch. Useful for displaying side-by-side diff.
@@ -225,7 +193,6 @@ public final class DiffRowGenerator {
public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) { public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) {
return generateDiffRows(original, DiffUtils.diff(original, revised, equalizer)); return generateDiffRows(original, DiffUtils.diff(original, revised, equalizer));
} }
/** /**
* Generates the DiffRows describing the difference between original and * Generates the DiffRows describing the difference between original and
* revised texts using the given patch. Useful for displaying side-by-side * revised texts using the given patch. Useful for displaying side-by-side
@@ -239,7 +206,6 @@ public final class DiffRowGenerator {
List<DiffRow> diffRows = new ArrayList<>(); List<DiffRow> diffRows = new ArrayList<>();
int endPos = 0; int endPos = 0;
final List<AbstractDelta<String>> deltaList = patch.getDeltas(); final List<AbstractDelta<String>> deltaList = patch.getDeltas();
if (decompressDeltas) { if (decompressDeltas) {
for (AbstractDelta<String> originalDelta : deltaList) { for (AbstractDelta<String> originalDelta : deltaList) {
for (AbstractDelta<String> delta : decompressDeltas(originalDelta)) { for (AbstractDelta<String> delta : decompressDeltas(originalDelta)) {
@@ -251,25 +217,21 @@ public final class DiffRowGenerator {
endPos = transformDeltaIntoDiffRow(original, endPos, diffRows, delta); endPos = transformDeltaIntoDiffRow(original, endPos, diffRows, delta);
} }
} }
// Copy the final matching chunk if any. // Copy the final matching chunk if any.
for (String line : original.subList(endPos, original.size())) { for (String line : original.subList(endPos, original.size())) {
diffRows.add(buildDiffRow(Tag.EQUAL, line, line)); diffRows.add(buildDiffRow(Tag.EQUAL, line, line));
} }
return diffRows; return diffRows;
} }
/** /**
* Transforms one patch delta into a DiffRow object. * Transforms one patch delta into a DiffRow object.
*/ */
private int transformDeltaIntoDiffRow(final List<String> original, int endPos, List<DiffRow> diffRows, AbstractDelta<String> delta) { private int transformDeltaIntoDiffRow(final List<String> original, int endPos, List<DiffRow> diffRows, AbstractDelta<String> delta) {
Chunk<String> orig = delta.getSource(); Chunk<String> orig = delta.getSource();
Chunk<String> rev = delta.getTarget(); Chunk<String> rev = delta.getTarget();
for (String line : original.subList(endPos, orig.getPosition())) { for (String line : original.subList(endPos, orig.getPosition())) {
diffRows.add(buildDiffRow(Tag.EQUAL, line, line)); diffRows.add(buildDiffRow(Tag.EQUAL, line, line));
} }
switch (delta.getType()) { switch (delta.getType()) {
case INSERT: case INSERT:
for (String line : rev.getLines()) { for (String line : rev.getLines()) {
@@ -292,10 +254,8 @@ public final class DiffRowGenerator {
} }
} }
} }
return orig.last() + 1; return orig.last() + 1;
} }
/** /**
* Decompresses ChangeDeltas with different source and target size to a * Decompresses ChangeDeltas with different source and target size to a
* ChangeDelta with same size and a following InsertDelta or DeleteDelta. * ChangeDelta with same size and a following InsertDelta or DeleteDelta.
@@ -307,15 +267,12 @@ public final class DiffRowGenerator {
if (delta.getType() == DeltaType.CHANGE && delta.getSource().size() != delta.getTarget().size()) { if (delta.getType() == DeltaType.CHANGE && delta.getSource().size() != delta.getTarget().size()) {
List<AbstractDelta<String>> deltas = new ArrayList<>(); List<AbstractDelta<String>> deltas = new ArrayList<>();
//System.out.println("decompress this " + delta); //System.out.println("decompress this " + delta);
int minSize = Math.min(delta.getSource().size(), delta.getTarget().size()); int minSize = Math.min(delta.getSource().size(), delta.getTarget().size());
Chunk<String> orig = delta.getSource(); Chunk<String> orig = delta.getSource();
Chunk<String> rev = delta.getTarget(); Chunk<String> rev = delta.getTarget();
deltas.add(new ChangeDelta<String>( deltas.add(new ChangeDelta<String>(
new Chunk<>(orig.getPosition(), orig.getLines().subList(0, minSize)), new Chunk<>(orig.getPosition(), orig.getLines().subList(0, minSize)),
new Chunk<>(rev.getPosition(), rev.getLines().subList(0, minSize)))); new Chunk<>(rev.getPosition(), rev.getLines().subList(0, minSize))));
if (orig.getLines().size() < rev.getLines().size()) { if (orig.getLines().size() < rev.getLines().size()) {
deltas.add(new InsertDelta<String>( deltas.add(new InsertDelta<String>(
new Chunk<>(orig.getPosition() + minSize, Collections.emptyList()), new Chunk<>(orig.getPosition() + minSize, Collections.emptyList()),
@@ -327,10 +284,8 @@ public final class DiffRowGenerator {
} }
return deltas; return deltas;
} }
return Collections.singletonList(delta); return Collections.singletonList(delta);
} }
private DiffRow buildDiffRow(Tag type, String orgline, String newline) { private DiffRow buildDiffRow(Tag type, String orgline, String newline) {
if (reportLinesUnchanged) { if (reportLinesUnchanged) {
return new DiffRow(type, orgline, newline); return new DiffRow(type, orgline, newline);
@@ -352,13 +307,11 @@ public final class DiffRowGenerator {
return new DiffRow(type, wrapOrg, wrapNew); return new DiffRow(type, wrapOrg, wrapNew);
} }
} }
private DiffRow buildDiffRowWithoutNormalizing(Tag type, String orgline, String newline) { private DiffRow buildDiffRowWithoutNormalizing(Tag type, String orgline, String newline) {
return new DiffRow(type, return new DiffRow(type,
StringUtils.wrapText(orgline, columnWidth), StringUtils.wrapText(orgline, columnWidth),
StringUtils.wrapText(newline, columnWidth)); StringUtils.wrapText(newline, columnWidth));
} }
List<String> normalizeLines(List<String> list) { List<String> normalizeLines(List<String> list) {
return reportLinesUnchanged return reportLinesUnchanged
? list ? list
@@ -366,7 +319,6 @@ public final class DiffRowGenerator {
.map(lineNormalizer::apply) .map(lineNormalizer::apply)
.collect(toList()); .collect(toList());
} }
/** /**
* Add the inline diffs for given delta * Add the inline diffs for given delta
* *
@@ -379,15 +331,12 @@ public final class DiffRowGenerator {
List<String> revList; List<String> revList;
String joinedOrig = String.join("\n", orig); String joinedOrig = String.join("\n", orig);
String joinedRev = String.join("\n", rev); String joinedRev = String.join("\n", rev);
origList = inlineDiffSplitter.apply(joinedOrig); origList = inlineDiffSplitter.apply(joinedOrig);
revList = inlineDiffSplitter.apply(joinedRev); revList = inlineDiffSplitter.apply(joinedRev);
List<AbstractDelta<String>> originalInlineDeltas = DiffUtils.diff(origList, revList, equalizer) List<AbstractDelta<String>> originalInlineDeltas = DiffUtils.diff(origList, revList, equalizer)
.getDeltas(); .getDeltas();
List<AbstractDelta<String>> inlineDeltas = inlineDeltaMerger List<AbstractDelta<String>> inlineDeltas = inlineDeltaMerger
.apply(new InlineDeltaMergeInfo(originalInlineDeltas, origList, revList)); .apply(new InlineDeltaMergeInfo(originalInlineDeltas, origList, revList));
Collections.reverse(inlineDeltas); Collections.reverse(inlineDeltas);
for (AbstractDelta<String> inlineDelta : inlineDeltas) { for (AbstractDelta<String> inlineDelta : inlineDeltas) {
Chunk<String> inlineOrig = inlineDelta.getSource(); Chunk<String> inlineOrig = inlineDelta.getSource();
@@ -435,7 +384,6 @@ public final class DiffRowGenerator {
for (String character : revList) { for (String character : revList) {
revResult.append(character); revResult.append(character);
} }
List<String> original = Arrays.asList(origResult.toString().split("\n")); List<String> original = Arrays.asList(origResult.toString().split("\n"));
List<String> revised = Arrays.asList(revResult.toString().split("\n")); List<String> revised = Arrays.asList(revResult.toString().split("\n"));
List<DiffRow> diffRows = new ArrayList<>(); List<DiffRow> diffRows = new ArrayList<>();
@@ -447,7 +395,6 @@ public final class DiffRowGenerator {
} }
return diffRows; return diffRows;
} }
private String preprocessLine(String line) { private String preprocessLine(String line) {
if (columnWidth == 0) { if (columnWidth == 0) {
return lineNormalizer.apply(line); return lineNormalizer.apply(line);
@@ -455,24 +402,19 @@ public final class DiffRowGenerator {
return StringUtils.wrapText(lineNormalizer.apply(line), columnWidth); return StringUtils.wrapText(lineNormalizer.apply(line), columnWidth);
} }
} }
/** /**
* This class used for building the DiffRowGenerator. * This class used for building the DiffRowGenerator.
* *
* @author dmitry * @author dmitry
*
*/ */
public static class Builder { public static class Builder {
private boolean showInlineDiffs = false; private boolean showInlineDiffs = false;
private boolean ignoreWhiteSpaces = false; private boolean ignoreWhiteSpaces = false;
private boolean decompressDeltas = true; private boolean decompressDeltas = true;
private BiFunction<Tag, Boolean, String> oldTag private BiFunction<Tag, Boolean, String> oldTag
= (tag, f) -> f ? "<span class=\"editOldInline\">" : "</span>"; = (tag, f) -> f ? "<span class=\"editOldInline\">" : "</span>";
private BiFunction<Tag, Boolean, String> newTag private BiFunction<Tag, Boolean, String> newTag
= (tag, f) -> f ? "<span class=\"editNewInline\">" : "</span>"; = (tag, f) -> f ? "<span class=\"editNewInline\">" : "</span>";
private int columnWidth = 0; private int columnWidth = 0;
private boolean mergeOriginalRevised = false; private boolean mergeOriginalRevised = false;
private boolean reportLinesUnchanged = false; private boolean reportLinesUnchanged = false;
@@ -482,10 +424,8 @@ public final class DiffRowGenerator {
private BiPredicate<String, String> equalizer = null; private BiPredicate<String, String> equalizer = null;
private boolean replaceOriginalLinefeedInChangesWithSpaces = false; private boolean replaceOriginalLinefeedInChangesWithSpaces = false;
private Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger = DEFAULT_INLINE_DELTA_MERGER; private Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger = DEFAULT_INLINE_DELTA_MERGER;
private Builder() { private Builder() {
} }
/** /**
* Show inline diffs in generating diff rows or not. * Show inline diffs in generating diff rows or not.
* *
@@ -496,7 +436,6 @@ public final class DiffRowGenerator {
showInlineDiffs = val; showInlineDiffs = val;
return this; return this;
} }
/** /**
* Ignore white spaces in generating diff rows or not. * Ignore white spaces in generating diff rows or not.
* *
@@ -507,7 +446,6 @@ public final class DiffRowGenerator {
ignoreWhiteSpaces = val; ignoreWhiteSpaces = val;
return this; return this;
} }
/** /**
* Report all lines without markup on the old or new text. * Report all lines without markup on the old or new text.
* *
@@ -518,7 +456,6 @@ public final class DiffRowGenerator {
reportLinesUnchanged = val; reportLinesUnchanged = val;
return this; return this;
} }
/** /**
* Generator for Old-Text-Tags. * Generator for Old-Text-Tags.
* *
@@ -529,7 +466,6 @@ public final class DiffRowGenerator {
this.oldTag = generator; this.oldTag = generator;
return this; return this;
} }
/** /**
* Generator for Old-Text-Tags. * Generator for Old-Text-Tags.
* *
@@ -540,7 +476,6 @@ public final class DiffRowGenerator {
this.oldTag = (tag, f) -> generator.apply(f); this.oldTag = (tag, f) -> generator.apply(f);
return this; return this;
} }
/** /**
* Generator for New-Text-Tags. * Generator for New-Text-Tags.
* *
@@ -551,7 +486,6 @@ public final class DiffRowGenerator {
this.newTag = generator; this.newTag = generator;
return this; return this;
} }
/** /**
* Generator for New-Text-Tags. * Generator for New-Text-Tags.
* *
@@ -562,7 +496,6 @@ public final class DiffRowGenerator {
this.newTag = (tag, f) -> generator.apply(f); this.newTag = (tag, f) -> generator.apply(f);
return this; return this;
} }
/** /**
* Processor for diffed text parts. Here e.g. whitecharacters could be * Processor for diffed text parts. Here e.g. whitecharacters could be
* replaced by something visible. * replaced by something visible.
@@ -574,7 +507,6 @@ public final class DiffRowGenerator {
this.processDiffs = processDiffs; this.processDiffs = processDiffs;
return this; return this;
} }
/** /**
* Set the column width of generated lines of original and revised * Set the column width of generated lines of original and revised
* texts. * texts.
@@ -589,7 +521,6 @@ public final class DiffRowGenerator {
} }
return this; return this;
} }
/** /**
* Build the DiffRowGenerator. If some parameters is not set, the * Build the DiffRowGenerator. If some parameters is not set, the
* default values are used. * default values are used.
@@ -599,7 +530,6 @@ public final class DiffRowGenerator {
public DiffRowGenerator build() { public DiffRowGenerator build() {
return new DiffRowGenerator(this); return new DiffRowGenerator(this);
} }
/** /**
* Merge the complete result within the original text. This makes sense * Merge the complete result within the original text. This makes sense
* for one line display. * for one line display.
@@ -611,7 +541,6 @@ public final class DiffRowGenerator {
this.mergeOriginalRevised = mergeOriginalRevised; this.mergeOriginalRevised = mergeOriginalRevised;
return this; return this;
} }
/** /**
* Deltas could be in a state, that would produce some unreasonable * Deltas could be in a state, that would produce some unreasonable
* results within an inline diff. So the deltas are decompressed into * results within an inline diff. So the deltas are decompressed into
@@ -624,7 +553,6 @@ public final class DiffRowGenerator {
this.decompressDeltas = decompressDeltas; this.decompressDeltas = decompressDeltas;
return this; return this;
} }
/** /**
* Per default each character is separatly processed. This variant * Per default each character is separatly processed. This variant
* introduces processing by word, which does not deliver in word * introduces processing by word, which does not deliver in word
@@ -639,7 +567,6 @@ public final class DiffRowGenerator {
inlineDiffSplitter = inlineDiffByWord ? SPLITTER_BY_WORD : SPLITTER_BY_CHARACTER; inlineDiffSplitter = inlineDiffByWord ? SPLITTER_BY_WORD : SPLITTER_BY_CHARACTER;
return this; return this;
} }
/** /**
* To provide some customized splitting a splitter can be provided. Here * To provide some customized splitting a splitter can be provided. Here
* someone could think about sentence splitter, comma splitter or stuff * someone could think about sentence splitter, comma splitter or stuff
@@ -652,7 +579,6 @@ public final class DiffRowGenerator {
this.inlineDiffSplitter = inlineDiffSplitter; this.inlineDiffSplitter = inlineDiffSplitter;
return this; return this;
} }
/** /**
* By default DiffRowGenerator preprocesses lines for HTML output. Tabs * By default DiffRowGenerator preprocesses lines for HTML output. Tabs
* and special HTML characters like "&lt;" are replaced with its encoded * and special HTML characters like "&lt;" are replaced with its encoded
@@ -666,7 +592,6 @@ public final class DiffRowGenerator {
this.lineNormalizer = lineNormalizer; this.lineNormalizer = lineNormalizer;
return this; return this;
} }
/** /**
* Provide an equalizer for diff processing. * Provide an equalizer for diff processing.
* *
@@ -677,7 +602,6 @@ public final class DiffRowGenerator {
this.equalizer = equalizer; this.equalizer = equalizer;
return this; return this;
} }
/** /**
* Sometimes it happens that a change contains multiple lines. If there * Sometimes it happens that a change contains multiple lines. If there
* is no correspondence in old and new. To keep the merged line more * is no correspondence in old and new. To keep the merged line more
@@ -690,7 +614,6 @@ public final class DiffRowGenerator {
this.replaceOriginalLinefeedInChangesWithSpaces = replace; this.replaceOriginalLinefeedInChangesWithSpaces = replace;
return this; return this;
} }
/** /**
* Provide an inline delta merger for use case specific delta optimizations. * Provide an inline delta merger for use case specific delta optimizations.
* *

View File

@@ -14,12 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.text; package com.github.difflib.text;
import java.util.List; import java.util.List;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
final class StringUtils { final class StringUtils {
private StringUtils() {
}
/** /**
* Replaces all opening and closing tags with <code>&lt;</code> or <code>&gt;</code>. * Replaces all opening and closing tags with <code>&lt;</code> or <code>&gt;</code>.
* *
@@ -29,17 +29,14 @@ final class StringUtils {
public static String htmlEntites(String str) { public static String htmlEntites(String str) {
return str.replace("<", "&lt;").replace(">", "&gt;"); return str.replace("<", "&lt;").replace(">", "&gt;");
} }
public static String normalize(String str) { public static String normalize(String str) {
return htmlEntites(str).replace("\t", " "); return htmlEntites(str).replace("\t", " ");
} }
public static List<String> wrapText(List<String> list, int columnWidth) { public static List<String> wrapText(List<String> list, int columnWidth) {
return list.stream() return list.stream()
.map(line -> wrapText(line, columnWidth)) .map(line -> wrapText(line, columnWidth))
.collect(toList()); .collect(toList());
} }
/** /**
* Wrap the text with the given column width * Wrap the text with the given column width
* *
@@ -57,9 +54,7 @@ final class StringUtils {
int length = line.length(); int length = line.length();
int delimiter = "<br/>".length(); int delimiter = "<br/>".length();
int widthIndex = columnWidth; int widthIndex = columnWidth;
StringBuilder b = new StringBuilder(line); StringBuilder b = new StringBuilder(line);
for (int count = 0; length > widthIndex; count++) { for (int count = 0; length > widthIndex; count++) {
int breakPoint = widthIndex + delimiter * count; int breakPoint = widthIndex + delimiter * count;
if (Character.isHighSurrogate(b.charAt(breakPoint - 1)) && if (Character.isHighSurrogate(b.charAt(breakPoint - 1)) &&
@@ -74,10 +69,6 @@ final class StringUtils {
b.insert(breakPoint, "<br/>"); b.insert(breakPoint, "<br/>");
widthIndex += columnWidth; widthIndex += columnWidth;
} }
return b.toString(); return b.toString();
} }
private StringUtils() {
}
} }

View File

@@ -14,39 +14,35 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.text.deltamerge; package com.github.difflib.text.deltamerge;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import com.github.difflib.patch.AbstractDelta; import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.ChangeDelta; import com.github.difflib.patch.ChangeDelta;
import com.github.difflib.patch.Chunk; import com.github.difflib.patch.Chunk;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/** /**
* Provides utility features for merge inline deltas * Provides utility features for merge inline deltas
* *
* @author <a href="christian.meier@epictec.ch">Christian Meier</a> * @author <a href="christian.meier@epictec.ch">Christian Meier</a>
*/ */
final public class DeltaMergeUtils { final public class DeltaMergeUtils {
private DeltaMergeUtils() {
}
public static List<AbstractDelta<String>> mergeInlineDeltas(InlineDeltaMergeInfo deltaMergeInfo, public static List<AbstractDelta<String>> mergeInlineDeltas(InlineDeltaMergeInfo deltaMergeInfo,
Predicate<List<String>> replaceEquality) { Predicate<List<String>> replaceEquality) {
final List<AbstractDelta<String>> originalDeltas = deltaMergeInfo.getDeltas(); final List<AbstractDelta<String>> originalDeltas = deltaMergeInfo.getDeltas();
if (originalDeltas.size() < 2) { if (originalDeltas.size() < 2) {
return originalDeltas; return originalDeltas;
} }
final List<AbstractDelta<String>> newDeltas = new ArrayList<>(); final List<AbstractDelta<String>> newDeltas = new ArrayList<>();
newDeltas.add(originalDeltas.get(0)); newDeltas.add(originalDeltas.get(0));
for (int i = 1; i < originalDeltas.size(); i++) { for (int i = 1; i < originalDeltas.size(); i++) {
final AbstractDelta<String> previousDelta = newDeltas.get(newDeltas.size() - 1); final AbstractDelta<String> previousDelta = newDeltas.get(newDeltas.size() - 1);
final AbstractDelta<String> currentDelta = originalDeltas.get(i); final AbstractDelta<String> currentDelta = originalDeltas.get(i);
final List<String> equalities = deltaMergeInfo.getOrigList().subList( final List<String> equalities = deltaMergeInfo.getOrigList().subList(
previousDelta.getSource().getPosition() + previousDelta.getSource().size(), previousDelta.getSource().getPosition() + previousDelta.getSource().size(),
currentDelta.getSource().getPosition()); currentDelta.getSource().getPosition());
if (replaceEquality.test(equalities)) { if (replaceEquality.test(equalities)) {
// Merge the previous delta, the equality and the current delta into one // Merge the previous delta, the equality and the current delta into one
// ChangeDelta and replace the previous delta by this new ChangeDelta. // ChangeDelta and replace the previous delta by this new ChangeDelta.
@@ -54,26 +50,19 @@ final public class DeltaMergeUtils {
allSourceLines.addAll(previousDelta.getSource().getLines()); allSourceLines.addAll(previousDelta.getSource().getLines());
allSourceLines.addAll(equalities); allSourceLines.addAll(equalities);
allSourceLines.addAll(currentDelta.getSource().getLines()); allSourceLines.addAll(currentDelta.getSource().getLines());
final List<String> allTargetLines = new ArrayList<>(); final List<String> allTargetLines = new ArrayList<>();
allTargetLines.addAll(previousDelta.getTarget().getLines()); allTargetLines.addAll(previousDelta.getTarget().getLines());
allTargetLines.addAll(equalities); allTargetLines.addAll(equalities);
allTargetLines.addAll(currentDelta.getTarget().getLines()); allTargetLines.addAll(currentDelta.getTarget().getLines());
final ChangeDelta<String> replacement = new ChangeDelta<>( final ChangeDelta<String> replacement = new ChangeDelta<>(
new Chunk<>(previousDelta.getSource().getPosition(), allSourceLines), new Chunk<>(previousDelta.getSource().getPosition(), allSourceLines),
new Chunk<>(previousDelta.getTarget().getPosition(), allTargetLines)); new Chunk<>(previousDelta.getTarget().getPosition(), allTargetLines));
newDeltas.remove(newDeltas.size() - 1); newDeltas.remove(newDeltas.size() - 1);
newDeltas.add(replacement); newDeltas.add(replacement);
} else { } else {
newDeltas.add(currentDelta); newDeltas.add(currentDelta);
} }
} }
return newDeltas; return newDeltas;
} }
private DeltaMergeUtils() {
}
} }

View File

@@ -14,11 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.text.deltamerge; package com.github.difflib.text.deltamerge;
import java.util.List;
import com.github.difflib.patch.AbstractDelta; import com.github.difflib.patch.AbstractDelta;
import java.util.List;
/** /**
* Holds the information required to merge deltas originating from an inline * Holds the information required to merge deltas originating from an inline
* diff * diff
@@ -26,25 +24,20 @@ import com.github.difflib.patch.AbstractDelta;
* @author <a href="christian.meier@epictec.ch">Christian Meier</a> * @author <a href="christian.meier@epictec.ch">Christian Meier</a>
*/ */
public final class InlineDeltaMergeInfo { public final class InlineDeltaMergeInfo {
private final List<AbstractDelta<String>> deltas; private final List<AbstractDelta<String>> deltas;
private final List<String> origList; private final List<String> origList;
private final List<String> revList; private final List<String> revList;
public InlineDeltaMergeInfo(List<AbstractDelta<String>> deltas, List<String> origList, List<String> revList) { public InlineDeltaMergeInfo(List<AbstractDelta<String>> deltas, List<String> origList, List<String> revList) {
this.deltas = deltas; this.deltas = deltas;
this.origList = origList; this.origList = origList;
this.revList = revList; this.revList = revList;
} }
public List<AbstractDelta<String>> getDeltas() { public List<AbstractDelta<String>> getDeltas() {
return deltas; return deltas;
} }
public List<String> getOrigList() { public List<String> getOrigList() {
return origList; return origList;
} }
public List<String> getRevList() { public List<String> getRevList() {
return revList; return revList;
} }

View File

@@ -14,47 +14,46 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.unifieddiff; package com.github.difflib.unifieddiff;
import com.github.difflib.patch.PatchFailedException; import com.github.difflib.patch.PatchFailedException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
*
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public final class UnifiedDiff { public final class UnifiedDiff {
private final List<UnifiedDiffFile> files = new ArrayList<>();
private String header; private String header;
private String tail; private String tail;
private final List<UnifiedDiffFile> files = new ArrayList<>(); public static UnifiedDiff from(String header, String tail, UnifiedDiffFile... files) {
UnifiedDiff diff = new UnifiedDiff();
diff.setHeader(header);
diff.setTailTxt(tail);
for (UnifiedDiffFile file : files) {
diff.addFile(file);
}
return diff;
}
public String getHeader() { public String getHeader() {
return header; return header;
} }
public void setHeader(String header) { public void setHeader(String header) {
this.header = header; this.header = header;
} }
void addFile(UnifiedDiffFile file) { void addFile(UnifiedDiffFile file) {
files.add(file); files.add(file);
} }
public List<UnifiedDiffFile> getFiles() { public List<UnifiedDiffFile> getFiles() {
return Collections.unmodifiableList(files); return Collections.unmodifiableList(files);
} }
void setTailTxt(String tailTxt) { void setTailTxt(String tailTxt) {
this.tail = tailTxt; this.tail = tailTxt;
} }
public String getTail() { public String getTail() {
return tail; return tail;
} }
public List<String> applyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException { public List<String> applyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException {
UnifiedDiffFile file = files.stream() UnifiedDiffFile file = files.stream()
.filter(diff -> findFile.test(diff.getFromFile())) .filter(diff -> findFile.test(diff.getFromFile()))
@@ -65,14 +64,4 @@ public final class UnifiedDiff {
return originalLines; return originalLines;
} }
} }
public static UnifiedDiff from(String header, String tail, UnifiedDiffFile... files) {
UnifiedDiff diff = new UnifiedDiff();
diff.setHeader(header);
diff.setTailTxt(tail);
for (UnifiedDiffFile file : files) {
diff.addFile(file);
}
return diff;
}
} }

View File

@@ -14,16 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.unifieddiff; package com.github.difflib.unifieddiff;
import com.github.difflib.patch.Patch; import com.github.difflib.patch.Patch;
/** /**
* Data structure for one patched file from a unified diff file. * Data structure for one patched file from a unified diff file.
* *
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public final class UnifiedDiffFile { public final class UnifiedDiffFile {
private String diffCommand; private String diffCommand;
private String fromFile; private String fromFile;
private String fromTimestamp; private String fromTimestamp;
@@ -44,99 +41,6 @@ public final class UnifiedDiffFile {
private Patch<String> patch = new Patch<>(); private Patch<String> patch = new Patch<>();
private boolean noNewLineAtTheEndOfTheFile = false; private boolean noNewLineAtTheEndOfTheFile = false;
private Integer similarityIndex; private Integer similarityIndex;
public String getDiffCommand() {
return diffCommand;
}
public void setDiffCommand(String diffCommand) {
this.diffCommand = diffCommand;
}
public String getFromFile() {
return fromFile;
}
public void setFromFile(String fromFile) {
this.fromFile = fromFile;
}
public String getToFile() {
return toFile;
}
public void setToFile(String toFile) {
this.toFile = toFile;
}
public void setIndex(String index) {
this.index = index;
}
public String getIndex() {
return index;
}
public Patch<String> getPatch() {
return patch;
}
public String getFromTimestamp() {
return fromTimestamp;
}
public void setFromTimestamp(String fromTimestamp) {
this.fromTimestamp = fromTimestamp;
}
public String getToTimestamp() {
return toTimestamp;
}
public void setToTimestamp(String toTimestamp) {
this.toTimestamp = toTimestamp;
}
public Integer getSimilarityIndex() {
return similarityIndex;
}
public void setSimilarityIndex(Integer similarityIndex) {
this.similarityIndex = similarityIndex;
}
public String getRenameFrom() {
return renameFrom;
}
public void setRenameFrom(String renameFrom) {
this.renameFrom = renameFrom;
}
public String getRenameTo() {
return renameTo;
}
public void setRenameTo(String renameTo) {
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) { public static UnifiedDiffFile from(String fromFile, String toFile, Patch<String> patch) {
UnifiedDiffFile file = new UnifiedDiffFile(); UnifiedDiffFile file = new UnifiedDiffFile();
file.setFromFile(fromFile); file.setFromFile(fromFile);
@@ -144,67 +48,120 @@ public final class UnifiedDiffFile {
file.patch = patch; file.patch = patch;
return file; return file;
} }
public String getDiffCommand() {
public void setNewFileMode(String newFileMode) { return diffCommand;
this.newFileMode = newFileMode; }
public void setDiffCommand(String diffCommand) {
this.diffCommand = diffCommand;
}
public String getFromFile() {
return fromFile;
}
public void setFromFile(String fromFile) {
this.fromFile = fromFile;
}
public String getToFile() {
return toFile;
}
public void setToFile(String toFile) {
this.toFile = toFile;
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public Patch<String> getPatch() {
return patch;
}
public String getFromTimestamp() {
return fromTimestamp;
}
public void setFromTimestamp(String fromTimestamp) {
this.fromTimestamp = fromTimestamp;
}
public String getToTimestamp() {
return toTimestamp;
}
public void setToTimestamp(String toTimestamp) {
this.toTimestamp = toTimestamp;
}
public Integer getSimilarityIndex() {
return similarityIndex;
}
public void setSimilarityIndex(Integer similarityIndex) {
this.similarityIndex = similarityIndex;
}
public String getRenameFrom() {
return renameFrom;
}
public void setRenameFrom(String renameFrom) {
this.renameFrom = renameFrom;
}
public String getRenameTo() {
return renameTo;
}
public void setRenameTo(String renameTo) {
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 String getNewFileMode() { public String getNewFileMode() {
return newFileMode; return newFileMode;
} }
public void setNewFileMode(String newFileMode) {
this.newFileMode = newFileMode;
}
public String getDeletedFileMode() { public String getDeletedFileMode() {
return deletedFileMode; return deletedFileMode;
} }
public void setDeletedFileMode(String deletedFileMode) { public void setDeletedFileMode(String deletedFileMode) {
this.deletedFileMode = deletedFileMode; this.deletedFileMode = deletedFileMode;
} }
public String getOldMode() { public String getOldMode() {
return oldMode; return oldMode;
} }
public void setOldMode(String oldMode) { public void setOldMode(String oldMode) {
this.oldMode = oldMode; this.oldMode = oldMode;
} }
public String getNewMode() { public String getNewMode() {
return newMode; return newMode;
} }
public void setNewMode(String newMode) { public void setNewMode(String newMode) {
this.newMode = newMode; this.newMode = newMode;
} }
public String getBinaryAdded() { public String getBinaryAdded() {
return binaryAdded; return binaryAdded;
} }
public void setBinaryAdded(String binaryAdded) { public void setBinaryAdded(String binaryAdded) {
this.binaryAdded = binaryAdded; this.binaryAdded = binaryAdded;
} }
public String getBinaryDeleted() { public String getBinaryDeleted() {
return binaryDeleted; return binaryDeleted;
} }
public void setBinaryDeleted(String binaryDeleted) { public void setBinaryDeleted(String binaryDeleted) {
this.binaryDeleted = binaryDeleted; this.binaryDeleted = binaryDeleted;
} }
public String getBinaryEdited() { public String getBinaryEdited() {
return binaryEdited; return binaryEdited;
} }
public void setBinaryEdited(String binaryEdited) { public void setBinaryEdited(String binaryEdited) {
this.binaryEdited = binaryEdited; this.binaryEdited = binaryEdited;
} }
public boolean isNoNewLineAtTheEndOfTheFile() { public boolean isNoNewLineAtTheEndOfTheFile() {
return noNewLineAtTheEndOfTheFile; return noNewLineAtTheEndOfTheFile;
} }
public void setNoNewLineAtTheEndOfTheFile(boolean noNewLineAtTheEndOfTheFile) { public void setNoNewLineAtTheEndOfTheFile(boolean noNewLineAtTheEndOfTheFile) {
this.noNewLineAtTheEndOfTheFile = noNewLineAtTheEndOfTheFile; this.noNewLineAtTheEndOfTheFile = noNewLineAtTheEndOfTheFile;
} }

View File

@@ -14,30 +14,22 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.unifieddiff; package com.github.difflib.unifieddiff;
/** /**
*
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public class UnifiedDiffParserException extends RuntimeException { public class UnifiedDiffParserException extends RuntimeException {
public UnifiedDiffParserException() { public UnifiedDiffParserException() {
} }
public UnifiedDiffParserException(String message) { public UnifiedDiffParserException(String message) {
super(message); super(message);
} }
public UnifiedDiffParserException(String message, Throwable cause) { public UnifiedDiffParserException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
public UnifiedDiffParserException(Throwable cause) { public UnifiedDiffParserException(Throwable cause) {
super(cause); super(cause);
} }
public UnifiedDiffParserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { public UnifiedDiffParserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace); super(message, cause, enableSuppression, writableStackTrace);
} }
} }

View File

@@ -14,14 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.unifieddiff; package com.github.difflib.unifieddiff;
import com.github.difflib.patch.ChangeDelta; import com.github.difflib.patch.ChangeDelta;
import com.github.difflib.patch.Chunk; import com.github.difflib.patch.Chunk;
import java.io.BufferedReader;
import java.io.IOException; import java.io.*;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -31,19 +27,16 @@ import java.util.logging.Logger;
import java.util.regex.MatchResult; import java.util.regex.MatchResult;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
*
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
*/ */
public final class UnifiedDiffReader { public final class UnifiedDiffReader {
static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern.compile("^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@"); static final Pattern UNIFIED_DIFF_CHUNK_REGEXP = Pattern.compile("^@@\\s+-(?:(\\d+)(?:,(\\d+))?)\\s+\\+(?:(\\d+)(?:,(\\d+))?)\\s+@@");
static final Pattern TIMESTAMP_REGEXP = Pattern.compile("(\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}\\.\\d{3,})(?: [+-]\\d+)?"); static final Pattern TIMESTAMP_REGEXP = Pattern.compile("(\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}\\.\\d{3,})(?: [+-]\\d+)?");
private static final Logger LOG = Logger.getLogger(UnifiedDiffReader.class.getName());
private final InternalUnifiedDiffReader READER; private final InternalUnifiedDiffReader READER;
private final UnifiedDiff data = new UnifiedDiff(); private final UnifiedDiff data = new UnifiedDiff();
private UnifiedDiffFile actualFile;
private final UnifiedDiffLine DIFF_COMMAND = new UnifiedDiffLine(true, "^diff\\s", this::processDiff); private final UnifiedDiffLine DIFF_COMMAND = new UnifiedDiffLine(true, "^diff\\s", this::processDiff);
private final UnifiedDiffLine SIMILARITY_INDEX = new UnifiedDiffLine(true, "^similarity index (\\d+)%$", this::processSimilarityIndex); private final UnifiedDiffLine SIMILARITY_INDEX = new UnifiedDiffLine(true, "^similarity index (\\d+)%$", this::processSimilarityIndex);
private final UnifiedDiffLine INDEX = new UnifiedDiffLine(true, "^index\\s[\\da-zA-Z]+\\.\\.[\\da-zA-Z]+(\\s(\\d+))?$", this::processIndex); private final UnifiedDiffLine INDEX = new UnifiedDiffLine(true, "^index\\s[\\da-zA-Z]+\\.\\.[\\da-zA-Z]+(\\s(\\d+))?$", this::processIndex);
@@ -51,29 +44,54 @@ public final class UnifiedDiffReader {
private final UnifiedDiffLine TO_FILE = new UnifiedDiffLine(true, "^\\+\\+\\+\\s", this::processToFile); 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_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 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_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 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 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 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 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 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_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_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 BINARY_EDITED = new UnifiedDiffLine(true, "^Binary\\sfiles\\sa/(.+)\\sand\\sb/(.+)\\sdiffer", this::processBinaryEdited);
private List<String> originalTxt = new ArrayList<>();
private List<String> revisedTxt = new ArrayList<>();
private List<Integer> addLineIdxList = new ArrayList<>();
private List<Integer> delLineIdxList = new ArrayList<>();
private int old_ln;
private int old_size;
private int new_ln;
private int new_size;
private final UnifiedDiffLine CHUNK = new UnifiedDiffLine(false, UNIFIED_DIFF_CHUNK_REGEXP, this::processChunk); private final UnifiedDiffLine CHUNK = new UnifiedDiffLine(false, UNIFIED_DIFF_CHUNK_REGEXP, this::processChunk);
private final UnifiedDiffLine LINE_NORMAL = new UnifiedDiffLine("^\\s", this::processNormalLine); private int delLineIdx = 0;
private final UnifiedDiffLine LINE_DEL = new UnifiedDiffLine("^-", this::processDelLine); private final UnifiedDiffLine LINE_DEL = new UnifiedDiffLine("^-", this::processDelLine);
private int addLineIdx = 0;
private final UnifiedDiffLine LINE_NORMAL = new UnifiedDiffLine("^\\s", this::processNormalLine);
private final UnifiedDiffLine LINE_ADD = new UnifiedDiffLine("^\\+", this::processAddLine); private final UnifiedDiffLine LINE_ADD = new UnifiedDiffLine("^\\+", this::processAddLine);
private UnifiedDiffFile actualFile;
UnifiedDiffReader(Reader reader) { UnifiedDiffReader(Reader reader) {
this.READER = new InternalUnifiedDiffReader(reader); this.READER = new InternalUnifiedDiffReader(reader);
} }
static String[] parseFileNames(String line) {
String[] split = line.split(" ");
return new String[]{
split[2].replaceAll("^a/", ""),
split[3].replaceAll("^b/", "")
};
}
/**
* To parse a diff file use this method.
*
* @param stream This is the diff file data.
* @return In a UnifiedDiff structure this diff file data is returned.
* @throws IOException
* @throws UnifiedDiffParserException
*/
public static UnifiedDiff parseUnifiedDiff(InputStream stream) throws IOException, UnifiedDiffParserException {
UnifiedDiffReader parser = new UnifiedDiffReader(new BufferedReader(new InputStreamReader(stream)));
return parser.parse();
}
private static Integer toInteger(MatchResult match, int group, int defValue) throws NumberFormatException {
return Integer.valueOf(Objects.toString(match.group(group), "" + defValue));
}
// schema = [[/^\s+/, normal], [/^diff\s/, start], [/^new file mode \d+$/, new_file], // schema = [[/^\s+/, normal], [/^diff\s/, start], [/^new file mode \d+$/, new_file],
// [/^deleted file mode \d+$/, deleted_file], [/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/, index], // [/^deleted file mode \d+$/, deleted_file], [/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/, index],
// [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk], // [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk],
@@ -96,7 +114,6 @@ public final class UnifiedDiffReader {
// if (!"".equals(headerTxt)) { // if (!"".equals(headerTxt)) {
// data.setHeader(headerTxt); // data.setHeader(headerTxt);
// } // }
String line = READER.readLine(); String line = READER.readLine();
while (line != null) { while (line != null) {
String headerTxt = ""; String headerTxt = "";
@@ -140,7 +157,6 @@ public final class UnifiedDiffReader {
processLine(line, CHUNK); processLine(line, CHUNK);
while ((line = READER.readLine()) != null) { while ((line = READER.readLine()) != null) {
line = checkForNoNewLineAtTheEndOfTheFile(line); line = checkForNoNewLineAtTheEndOfTheFile(line);
if (!processLine(line, LINE_NORMAL, LINE_ADD, LINE_DEL)) { if (!processLine(line, LINE_NORMAL, LINE_ADD, LINE_DEL)) {
throw new UnifiedDiffParserException("expected data line not found"); throw new UnifiedDiffParserException("expected data line not found");
} }
@@ -152,14 +168,12 @@ public final class UnifiedDiffReader {
} }
} }
line = READER.readLine(); line = READER.readLine();
line = checkForNoNewLineAtTheEndOfTheFile(line); line = checkForNoNewLineAtTheEndOfTheFile(line);
} }
if (line == null || (line.startsWith("--") && !line.startsWith("---"))) { if (line == null || (line.startsWith("--") && !line.startsWith("---"))) {
break; break;
} }
} }
if (READER.ready()) { if (READER.ready()) {
String tailTxt = ""; String tailTxt = "";
while (READER.ready()) { while (READER.ready()) {
@@ -170,10 +184,8 @@ public final class UnifiedDiffReader {
} }
data.setTailTxt(tailTxt); data.setTailTxt(tailTxt);
} }
return data; return data;
} }
private String checkForNoNewLineAtTheEndOfTheFile(String line) throws IOException { private String checkForNoNewLineAtTheEndOfTheFile(String line) throws IOException {
if ("\\ No newline at end of file".equals(line)) { if ("\\ No newline at end of file".equals(line)) {
actualFile.setNoNewLineAtTheEndOfTheFile(true); actualFile.setNoNewLineAtTheEndOfTheFile(true);
@@ -181,30 +193,6 @@ public final class UnifiedDiffReader {
} }
return line; return line;
} }
static String[] parseFileNames(String line) {
String[] split = line.split(" ");
return new String[]{
split[2].replaceAll("^a/", ""),
split[3].replaceAll("^b/", "")
};
}
private static final Logger LOG = Logger.getLogger(UnifiedDiffReader.class.getName());
/**
* To parse a diff file use this method.
*
* @param stream This is the diff file data.
* @return In a UnifiedDiff structure this diff file data is returned.
* @throws IOException
* @throws UnifiedDiffParserException
*/
public static UnifiedDiff parseUnifiedDiff(InputStream stream) throws IOException, UnifiedDiffParserException {
UnifiedDiffReader parser = new UnifiedDiffReader(new BufferedReader(new InputStreamReader(stream)));
return parser.parse();
}
private boolean processLine(String line, UnifiedDiffLine... rules) throws UnifiedDiffParserException { private boolean processLine(String line, UnifiedDiffLine... rules) throws UnifiedDiffParserException {
if (line == null) { if (line == null) {
return false; return false;
@@ -219,7 +207,6 @@ public final class UnifiedDiffReader {
return false; return false;
//throw new UnifiedDiffParserException("parsing error at line " + line); //throw new UnifiedDiffParserException("parsing error at line " + line);
} }
private boolean validLine(String line, UnifiedDiffLine... rules) { private boolean validLine(String line, UnifiedDiffLine... rules) {
if (line == null) { if (line == null) {
return false; return false;
@@ -232,7 +219,6 @@ public final class UnifiedDiffReader {
} }
return false; return false;
} }
private void initFileIfNecessary() { private void initFileIfNecessary() {
if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) { if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) {
throw new IllegalStateException(); throw new IllegalStateException();
@@ -243,7 +229,6 @@ public final class UnifiedDiffReader {
data.addFile(actualFile); data.addFile(actualFile);
} }
} }
private void processDiff(MatchResult match, String line) { private void processDiff(MatchResult match, String line) {
//initFileIfNecessary(); //initFileIfNecessary();
LOG.log(Level.FINE, "start {0}", line); LOG.log(Level.FINE, "start {0}", line);
@@ -252,22 +237,9 @@ public final class UnifiedDiffReader {
actualFile.setToFile(fromTo[1]); actualFile.setToFile(fromTo[1]);
actualFile.setDiffCommand(line); actualFile.setDiffCommand(line);
} }
private void processSimilarityIndex(MatchResult match, String line) { private void processSimilarityIndex(MatchResult match, String line) {
actualFile.setSimilarityIndex(Integer.valueOf(match.group(1))); actualFile.setSimilarityIndex(Integer.valueOf(match.group(1)));
} }
private List<String> originalTxt = new ArrayList<>();
private List<String> revisedTxt = new ArrayList<>();
private List<Integer> addLineIdxList = new ArrayList<>();
private List<Integer> delLineIdxList = new ArrayList<>();
private int old_ln;
private int old_size;
private int new_ln;
private int new_size;
private int delLineIdx = 0;
private int addLineIdx = 0;
private void finalizeChunk() { private void finalizeChunk() {
if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) { if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) {
actualFile.getPatch().addDelta(new ChangeDelta<>(new Chunk<>( actualFile.getPatch().addDelta(new ChangeDelta<>(new Chunk<>(
@@ -283,7 +255,6 @@ public final class UnifiedDiffReader {
addLineIdx = 0; addLineIdx = 0;
} }
} }
private void processNormalLine(MatchResult match, String line) { private void processNormalLine(MatchResult match, String line) {
String cline = line.substring(1); String cline = line.substring(1);
originalTxt.add(cline); originalTxt.add(cline);
@@ -291,21 +262,18 @@ public final class UnifiedDiffReader {
delLineIdx++; delLineIdx++;
addLineIdx++; addLineIdx++;
} }
private void processAddLine(MatchResult match, String line) { private void processAddLine(MatchResult match, String line) {
String cline = line.substring(1); String cline = line.substring(1);
revisedTxt.add(cline); revisedTxt.add(cline);
addLineIdx++; addLineIdx++;
addLineIdxList.add(new_ln - 1 + addLineIdx); addLineIdxList.add(new_ln - 1 + addLineIdx);
} }
private void processDelLine(MatchResult match, String line) { private void processDelLine(MatchResult match, String line) {
String cline = line.substring(1); String cline = line.substring(1);
originalTxt.add(cline); originalTxt.add(cline);
delLineIdx++; delLineIdx++;
delLineIdxList.add(old_ln - 1 + delLineIdx); delLineIdxList.add(old_ln - 1 + delLineIdx);
} }
private void processChunk(MatchResult match, String chunkStart) { private void processChunk(MatchResult match, String chunkStart) {
// finalizeChunk(); // finalizeChunk();
old_ln = toInteger(match, 1, 1); old_ln = toInteger(match, 1, 1);
@@ -319,75 +287,56 @@ public final class UnifiedDiffReader {
new_ln = 1; new_ln = 1;
} }
} }
private static Integer toInteger(MatchResult match, int group, int defValue) throws NumberFormatException {
return Integer.valueOf(Objects.toString(match.group(group), "" + defValue));
}
private void processIndex(MatchResult match, String line) { private void processIndex(MatchResult match, String line) {
//initFileIfNecessary(); //initFileIfNecessary();
LOG.log(Level.FINE, "index {0}", line); LOG.log(Level.FINE, "index {0}", line);
actualFile.setIndex(line.substring(6)); actualFile.setIndex(line.substring(6));
} }
private void processFromFile(MatchResult match, String line) { private void processFromFile(MatchResult match, String line) {
//initFileIfNecessary(); //initFileIfNecessary();
actualFile.setFromFile(extractFileName(line)); actualFile.setFromFile(extractFileName(line));
actualFile.setFromTimestamp(extractTimestamp(line)); actualFile.setFromTimestamp(extractTimestamp(line));
} }
private void processToFile(MatchResult match, String line) { private void processToFile(MatchResult match, String line) {
//initFileIfNecessary(); //initFileIfNecessary();
actualFile.setToFile(extractFileName(line)); actualFile.setToFile(extractFileName(line));
actualFile.setToTimestamp(extractTimestamp(line)); actualFile.setToTimestamp(extractTimestamp(line));
} }
private void processRenameFrom(MatchResult match, String line) { private void processRenameFrom(MatchResult match, String line) {
actualFile.setRenameFrom(match.group(1)); actualFile.setRenameFrom(match.group(1));
} }
private void processRenameTo(MatchResult match, String line) { private void processRenameTo(MatchResult match, String line) {
actualFile.setRenameTo(match.group(1)); actualFile.setRenameTo(match.group(1));
} }
private void processCopyFrom(MatchResult match, String line) { private void processCopyFrom(MatchResult match, String line) {
actualFile.setCopyFrom(match.group(1)); actualFile.setCopyFrom(match.group(1));
} }
private void processCopyTo(MatchResult match, String line) { private void processCopyTo(MatchResult match, String line) {
actualFile.setCopyTo(match.group(1)); actualFile.setCopyTo(match.group(1));
} }
private void processNewFileMode(MatchResult match, String line) { private void processNewFileMode(MatchResult match, String line) {
//initFileIfNecessary(); //initFileIfNecessary();
actualFile.setNewFileMode(match.group(1)); actualFile.setNewFileMode(match.group(1));
} }
private void processDeletedFileMode(MatchResult match, String line) { private void processDeletedFileMode(MatchResult match, String line) {
//initFileIfNecessary(); //initFileIfNecessary();
actualFile.setDeletedFileMode(match.group(1)); actualFile.setDeletedFileMode(match.group(1));
} }
private void processOldMode(MatchResult match, String line) { private void processOldMode(MatchResult match, String line) {
actualFile.setOldMode(match.group(1)); actualFile.setOldMode(match.group(1));
} }
private void processNewMode(MatchResult match, String line) { private void processNewMode(MatchResult match, String line) {
actualFile.setNewMode(match.group(1)); actualFile.setNewMode(match.group(1));
} }
private void processBinaryAdded(MatchResult match, String line) { private void processBinaryAdded(MatchResult match, String line) {
actualFile.setBinaryAdded(match.group(1)); actualFile.setBinaryAdded(match.group(1));
} }
private void processBinaryDeleted(MatchResult match, String line) { private void processBinaryDeleted(MatchResult match, String line) {
actualFile.setBinaryDeleted(match.group(1)); actualFile.setBinaryDeleted(match.group(1));
} }
private void processBinaryEdited(MatchResult match, String line) { private void processBinaryEdited(MatchResult match, String line) {
actualFile.setBinaryEdited(match.group(1)); actualFile.setBinaryEdited(match.group(1));
} }
private String extractFileName(String _line) { private String extractFileName(String _line) {
Matcher matcher = TIMESTAMP_REGEXP.matcher(_line); Matcher matcher = TIMESTAMP_REGEXP.matcher(_line);
String line = _line; String line = _line;
@@ -398,7 +347,6 @@ public final class UnifiedDiffReader {
return line.substring(4).replaceFirst("^(a|b|old|new)/", "") return line.substring(4).replaceFirst("^(a|b|old|new)/", "")
.trim(); .trim();
} }
private String extractTimestamp(String line) { private String extractTimestamp(String line) {
Matcher matcher = TIMESTAMP_REGEXP.matcher(line); Matcher matcher = TIMESTAMP_REGEXP.matcher(line);
if (matcher.find()) { if (matcher.find()) {
@@ -406,34 +354,27 @@ public final class UnifiedDiffReader {
} }
return null; return null;
} }
final class UnifiedDiffLine { final class UnifiedDiffLine {
private final Pattern pattern; private final Pattern pattern;
private final BiConsumer<MatchResult, String> command; private final BiConsumer<MatchResult, String> command;
private final boolean stopsHeaderParsing; private final boolean stopsHeaderParsing;
public UnifiedDiffLine(String pattern, BiConsumer<MatchResult, String> command) { public UnifiedDiffLine(String pattern, BiConsumer<MatchResult, String> command) {
this(false, pattern, command); this(false, pattern, command);
} }
public UnifiedDiffLine(boolean stopsHeaderParsing, String pattern, BiConsumer<MatchResult, String> command) { public UnifiedDiffLine(boolean stopsHeaderParsing, String pattern, BiConsumer<MatchResult, String> command) {
this.pattern = Pattern.compile(pattern); this.pattern = Pattern.compile(pattern);
this.command = command; this.command = command;
this.stopsHeaderParsing = stopsHeaderParsing; this.stopsHeaderParsing = stopsHeaderParsing;
} }
public UnifiedDiffLine(boolean stopsHeaderParsing, Pattern pattern, BiConsumer<MatchResult, String> command) { public UnifiedDiffLine(boolean stopsHeaderParsing, Pattern pattern, BiConsumer<MatchResult, String> command) {
this.pattern = pattern; this.pattern = pattern;
this.command = command; this.command = command;
this.stopsHeaderParsing = stopsHeaderParsing; this.stopsHeaderParsing = stopsHeaderParsing;
} }
public boolean validLine(String line) { public boolean validLine(String line) {
Matcher m = pattern.matcher(line); Matcher m = pattern.matcher(line);
return m.find(); return m.find();
} }
public boolean processLine(String line) throws UnifiedDiffParserException { public boolean processLine(String line) throws UnifiedDiffParserException {
Matcher m = pattern.matcher(line); Matcher m = pattern.matcher(line);
if (m.find()) { if (m.find()) {
@@ -443,32 +384,25 @@ public final class UnifiedDiffReader {
return false; return false;
} }
} }
public boolean isStopsHeaderParsing() { public boolean isStopsHeaderParsing() {
return stopsHeaderParsing; return stopsHeaderParsing;
} }
@Override @Override
public String toString() { public String toString() {
return "UnifiedDiffLine{" + "pattern=" + pattern + ", stopsHeaderParsing=" + stopsHeaderParsing + '}'; return "UnifiedDiffLine{" + "pattern=" + pattern + ", stopsHeaderParsing=" + stopsHeaderParsing + '}';
} }
} }
} }
class InternalUnifiedDiffReader extends BufferedReader { class InternalUnifiedDiffReader extends BufferedReader {
private String lastLine; private String lastLine;
public InternalUnifiedDiffReader(Reader reader) { public InternalUnifiedDiffReader(Reader reader) {
super(reader); super(reader);
} }
@Override @Override
public String readLine() throws IOException { public String readLine() throws IOException {
lastLine = super.readLine(); lastLine = super.readLine();
return lastLine(); return lastLine();
} }
String lastLine() { String lastLine() {
return lastLine; return lastLine;
} }

View File

@@ -14,8 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
package com.github.difflib.unifieddiff; package com.github.difflib.unifieddiff;
import com.github.difflib.patch.AbstractDelta; import com.github.difflib.patch.AbstractDelta;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
@@ -25,15 +25,12 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* @todo use an instance to store contextSize and originalLinesProvider.
* @author Tobias Warneke (t.warneke@gmx.net) * @author Tobias Warneke (t.warneke@gmx.net)
* @todo use an instance to store contextSize and originalLinesProvider.
*/ */
public class UnifiedDiffWriter { public class UnifiedDiffWriter {
private static final Logger LOG = Logger.getLogger(UnifiedDiffWriter.class.getName()); private static final Logger LOG = Logger.getLogger(UnifiedDiffWriter.class.getName());
public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Writer writer, int contextSize) throws IOException { public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Writer writer, int contextSize) throws IOException {
Objects.requireNonNull(originalLinesProvider, "original lines provider needs to be specified"); Objects.requireNonNull(originalLinesProvider, "original lines provider needs to be specified");
write(diff, originalLinesProvider, line -> { write(diff, originalLinesProvider, line -> {
@@ -44,12 +41,10 @@ public class UnifiedDiffWriter {
} }
}, contextSize); }, contextSize);
} }
public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Consumer<String> writer, int contextSize) throws IOException { public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Consumer<String> writer, int contextSize) throws IOException {
if (diff.getHeader() != null) { if (diff.getHeader() != null) {
writer.accept(diff.getHeader()); writer.accept(diff.getHeader());
} }
for (UnifiedDiffFile file : diff.getFiles()) { for (UnifiedDiffFile file : diff.getFiles()) {
List<AbstractDelta<String>> patchDeltas = new ArrayList<>( List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
file.getPatch().getDeltas()); file.getPatch().getDeltas());
@@ -58,24 +53,18 @@ public class UnifiedDiffWriter {
if (file.getIndex() != null) { if (file.getIndex() != null) {
writer.accept("index " + file.getIndex()); writer.accept("index " + file.getIndex());
} }
writer.accept("--- " + (file.getFromFile() == null ? "/dev/null" : file.getFromFile())); writer.accept("--- " + (file.getFromFile() == null ? "/dev/null" : file.getFromFile()));
if (file.getToFile() != null) { if (file.getToFile() != null) {
writer.accept("+++ " + file.getToFile()); writer.accept("+++ " + file.getToFile());
} }
List<String> originalLines = originalLinesProvider.apply(file.getFromFile()); List<String> originalLines = originalLinesProvider.apply(file.getFromFile());
List<AbstractDelta<String>> deltas = new ArrayList<>(); List<AbstractDelta<String>> deltas = new ArrayList<>();
AbstractDelta<String> delta = patchDeltas.get(0); AbstractDelta<String> delta = patchDeltas.get(0);
deltas.add(delta); // add the first Delta to the current set deltas.add(delta); // add the first Delta to the current set
// if there's more than 1 Delta, we may need to output them together // if there's more than 1 Delta, we may need to output them together
if (patchDeltas.size() > 1) { if (patchDeltas.size() > 1) {
for (int i = 1; i < patchDeltas.size(); i++) { for (int i = 1; i < patchDeltas.size(); i++) {
int position = delta.getSource().getPosition(); int position = delta.getSource().getPosition();
// Check if the next Delta is too close to the current // Check if the next Delta is too close to the current
// position. // position.
// And if it is, add it to the current set // And if it is, add it to the current set
@@ -93,20 +82,17 @@ public class UnifiedDiffWriter {
} }
delta = nextDelta; delta = nextDelta;
} }
} }
// don't forget to process the last set of Deltas // don't forget to process the last set of Deltas
processDeltas(writer, originalLines, deltas, contextSize, processDeltas(writer, originalLines, deltas, contextSize,
patchDeltas.size() == 1 && file.getFromFile() == null); patchDeltas.size() == 1 && file.getFromFile() == null);
} }
} }
if (diff.getTail() != null) { if (diff.getTail() != null) {
writer.accept("--"); writer.accept("--");
writer.accept(diff.getTail()); writer.accept(diff.getTail());
} }
} }
private static void processDeltas(Consumer<String> writer, private static void processDeltas(Consumer<String> writer,
List<String> origLines, List<AbstractDelta<String>> deltas, List<String> origLines, List<AbstractDelta<String>> deltas,
int contextSize, boolean newFile) { int contextSize, boolean newFile) {
@@ -114,9 +100,7 @@ public class UnifiedDiffWriter {
int origTotal = 0; // counter for total lines output from Original int origTotal = 0; // counter for total lines output from Original
int revTotal = 0; // counter for total lines output from Original int revTotal = 0; // counter for total lines output from Original
int line; int line;
AbstractDelta<String> curDelta = deltas.get(0); AbstractDelta<String> curDelta = deltas.get(0);
int origStart; int origStart;
if (newFile) { if (newFile) {
origStart = 0; origStart = 0;
@@ -127,18 +111,15 @@ public class UnifiedDiffWriter {
origStart = 1; origStart = 1;
} }
} }
int revStart = curDelta.getTarget().getPosition() + 1 - contextSize; int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
if (revStart < 1) { if (revStart < 1) {
revStart = 1; revStart = 1;
} }
// find the start of the wrapper context code // find the start of the wrapper context code
int contextStart = curDelta.getSource().getPosition() - contextSize; int contextStart = curDelta.getSource().getPosition() - contextSize;
if (contextStart < 0) { if (contextStart < 0) {
contextStart = 0; // clamp to the start of the file contextStart = 0; // clamp to the start of the file
} }
// output the context before the first Delta // output the context before the first Delta
for (line = contextStart; line < curDelta.getSource().getPosition() for (line = contextStart; line < curDelta.getSource().getPosition()
&& line < origLines.size(); line++) { // && line < origLines.size(); line++) { //
@@ -150,7 +131,6 @@ public class UnifiedDiffWriter {
getDeltaText(txt -> buffer.add(txt), curDelta); getDeltaText(txt -> buffer.add(txt), curDelta);
origTotal += curDelta.getSource().getLines().size(); origTotal += curDelta.getSource().getLines().size();
revTotal += curDelta.getTarget().getLines().size(); revTotal += curDelta.getTarget().getLines().size();
int deltaIndex = 1; int deltaIndex = 1;
while (deltaIndex < deltas.size()) { // for each of the other Deltas while (deltaIndex < deltas.size()) { // for each of the other Deltas
AbstractDelta<String> nextDelta = deltas.get(deltaIndex); AbstractDelta<String> nextDelta = deltas.get(deltaIndex);
@@ -169,7 +149,6 @@ public class UnifiedDiffWriter {
curDelta = nextDelta; curDelta = nextDelta;
deltaIndex++; deltaIndex++;
} }
// Now output the post-Delta context code, clamping the end of the file // Now output the post-Delta context code, clamping the end of the file
contextStart = curDelta.getSource().getPosition() contextStart = curDelta.getSource().getPosition()
+ curDelta.getSource().getLines().size(); + curDelta.getSource().getLines().size();
@@ -179,7 +158,6 @@ public class UnifiedDiffWriter {
origTotal++; origTotal++;
revTotal++; revTotal++;
} }
// Create and insert the block header, conforming to the Unified Diff // Create and insert the block header, conforming to the Unified Diff
// standard // standard
writer.accept("@@ -" + origStart + "," + origTotal + " +" + revStart + "," + revTotal + " @@"); writer.accept("@@ -" + origStart + "," + origTotal + " +" + revStart + "," + revTotal + " @@");
@@ -187,7 +165,6 @@ public class UnifiedDiffWriter {
writer.accept(txt); writer.accept(txt);
}); });
} }
/** /**
* 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.
* *
@@ -202,7 +179,6 @@ public class UnifiedDiffWriter {
writer.accept("+" + line); writer.accept("+" + line);
} }
} }
private static void writeOrNothing(Consumer<String> writer, String str) throws IOException { private static void writeOrNothing(Consumer<String> writer, String str) throws IOException {
if (str != null) { if (str != null) {
writer.accept(str); writer.accept(str);