package org.mian.gitnex.helpers; import org.gitnex.tea4j.models.FileDiffView; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Author 6543 */ public class ParseDiff { private static String[] getFileNames(String raw) { String[] lines2 = raw.split(" b/"); if(lines2.length < 2) { return new String[1]; } String oldName = lines2[0]; String newName = lines2[1].split("\\n")[0]; return new String[]{oldName, newName}; } private static String getFileInfo(String raw) { if(raw.contains("\ndeleted file mode \\d+\n")) { return "delete"; } else if(raw.contains("\nnew file mode \\d+\n")) { return "new"; } return "change"; } private static int[] countRemoveAdd(String raw) { int rm = 0, add = 0; Pattern rmPattern = Pattern.compile("\n-"); Pattern addPattern = Pattern.compile("\n\\+"); Matcher rmMatcher = rmPattern.matcher(raw); Matcher addMatcher = addPattern.matcher(raw); while(rmMatcher.find()) rm++; while(addMatcher.find()) add++; return new int[]{rm, add}; } public static List getFileDiffViewArray(String raw) { List fileContentsArray = new ArrayList<>(); String[] lines = raw.split("(^|\\n)diff --git a/"); if(lines.length > 1) { // for each file in diff for(int i = 1; i < lines.length; i++) { // check if it is a binary file if(lines[i].contains("\nBinary files a/")) { String[] fileNames = getFileNames(lines[i]); if(fileNames.length != 2) { continue; } fileContentsArray.add(new FileDiffView(fileNames[0], fileNames[1], "binary", "", null)); } // check if it is a binary patch else if(lines[i].contains("\nGIT binary patch\n")) { String[] fileNames = getFileNames(lines[i]); if(fileNames.length != 2) { continue; } String[] tmp = lines[i].split("literal \\d+\\n"); String rawContent = ""; if(tmp.length >= 2) { rawContent = tmp[1].replace("\n", ""); } List contents = new ArrayList<>(); contents.add(new FileDiffView.Content(rawContent)); fileContentsArray.add(new FileDiffView(fileNames[0], fileNames[1], "binary", getFileInfo(lines[i]), contents)); } // check if it is normal diff else if(lines[i].contains("\n@@ -")) { String[] fileNames = getFileNames(lines[i]); if(fileNames.length != 2) { continue; } String[] rawDiffs = lines[i].split("\n@@ -"); if(rawDiffs.length <= 1) { continue; } List contents = new ArrayList<>(); // parse each section starting with "@@" at line beginning for(int j = 1; j < rawDiffs.length; j++) { // remove stats info (ending with @@) // raw diff is the whole raw diff without any diff meta info's String[] rawDiff = rawDiffs[j].split("^\\d+(,\\d+)? \\+\\d+(,\\d+)? @@"); if(rawDiff.length <= 1) { continue; } // extract the diff stats info of the first line String statsLine = rawDiffs[j].split("\n")[0].split(" @@")[0]; // parse "-1,2 +2,3" and "-1 -3" and so on int oldStart = 0, newStart = 0; String diffPos[] = statsLine.split(" \\+"); if(diffPos.length == 2) { oldStart = Integer.parseInt(diffPos[0].split(",")[0]); newStart = Integer.parseInt(diffPos[1].split(",")[0]); } // get stat int[] stats = countRemoveAdd(rawDiff[1]); contents.add(new FileDiffView.Content(rawDiff[1], oldStart, newStart, stats[0], stats[1])); } fileContentsArray.add(new FileDiffView(fileNames[0], fileNames[1], "diff", getFileInfo(lines[i]), contents)); } // a rename else if(lines[i].contains("\nrename from")) { String[] lines2 = lines[i].split("\\nrename (from|to )"); if(lines2.length != 3) { continue; } fileContentsArray.add(new FileDiffView(lines2[1], lines2[2].split("\\n")[0], "rename", "rename", null)); } } } return fileContentsArray; } }