2020import java .io .InputStream ;
2121import java .io .InputStreamReader ;
2222import java .io .Reader ;
23+ import java .util .ArrayList ;
24+ import java .util .List ;
2325import java .util .function .BiConsumer ;
2426import java .util .logging .Level ;
2527import java .util .logging .Logger ;
3335 */
3436public final class UnifiedDiffParser {
3537
38+ private static final String UNIFIED_DIFF_CHUNK_REGEXP = "^@@\\ s+-(?:(\\ d+)(?:,(\\ d+))?)\\ s+\\ +(?:(\\ d+)(?:,(\\ d+))?)\\ s+@@$" ;
39+
3640 private final UnifiedDiffReader READER ;
3741 private final UnifiedDiff data = new UnifiedDiff ();
38- private final UnifiedDiffLine [] PARSER_RULES = new UnifiedDiffLine []{
39- new UnifiedDiffLine ("^\\ s+" , (m , l ) -> LOG .info ("normal " + l )),
42+ private final UnifiedDiffLine [] MAIN_PARSER_RULES = new UnifiedDiffLine []{
4043 new UnifiedDiffLine (true , "^diff\\ s" , this ::processDiff ),
41- new UnifiedDiffLine (true , "^index\\ s[\\ da-zA-Z]+\\ .\\ .[\\ da-zA-Z]+(\\ s(\\ d+))?$" , this ::processIndex )
44+ new UnifiedDiffLine (true , "^index\\ s[\\ da-zA-Z]+\\ .\\ .[\\ da-zA-Z]+(\\ s(\\ d+))?$" , this ::processIndex ),
45+ new UnifiedDiffLine (true , "^---\\ s" , this ::processFromFile ),
46+ new UnifiedDiffLine (true , "^\\ +\\ +\\ +\\ s" , this ::processToFile ),
47+ new UnifiedDiffLine (true , UNIFIED_DIFF_CHUNK_REGEXP , this ::processChunk )
4248 };
49+
4350 private UnifiedDiffFile actualFile ;
4451
4552 UnifiedDiffParser (Reader reader ) {
@@ -50,7 +57,7 @@ public final class UnifiedDiffParser {
5057 // [/^deleted file mode \d+$/, deleted_file], [/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/, index],
5158 // [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk],
5259 // [/^-/, del], [/^\+/, add], [/^\\ No newline at end of file$/, eof]];
53- private UnifiedDiff parse () throws IOException {
60+ private UnifiedDiff parse () throws IOException , UnifiedDiffParserException {
5461 boolean header = true ;
5562 String headerTxt = "" ;
5663 while (READER .ready ()) {
@@ -79,13 +86,13 @@ static String[] parseFileNames(String line) {
7986
8087 private static final Logger LOG = Logger .getLogger (UnifiedDiffParser .class .getName ());
8188
82- public static UnifiedDiff parseUnifiedDiff (InputStream stream ) throws IOException {
89+ public static UnifiedDiff parseUnifiedDiff (InputStream stream ) throws IOException , UnifiedDiffParserException {
8390 UnifiedDiffParser parser = new UnifiedDiffParser (new BufferedReader (new InputStreamReader (stream )));
8491 return parser .parse ();
8592 }
8693
87- private boolean processLine (boolean header , String line ) {
88- for (UnifiedDiffLine rule : PARSER_RULES ) {
94+ private boolean processLine (boolean header , String line ) throws UnifiedDiffParserException {
95+ for (UnifiedDiffLine rule : MAIN_PARSER_RULES ) {
8996 if (header && rule .isStopsHeaderParsing () || !header ) {
9097 if (rule .processLine (line )) {
9198 return true ;
@@ -108,6 +115,35 @@ public void processDiff(MatchResult match, String line) {
108115 String [] fromTo = parseFileNames (READER .lastLine ());
109116 actualFile .setFromFile (fromTo [0 ]);
110117 actualFile .setToFile (fromTo [1 ]);
118+ actualFile .setDiffCommand (line );
119+ }
120+
121+ public void processChunk (MatchResult match , String chunkStart ) {
122+ try {
123+ List <String > originalTxt = new ArrayList <>();
124+ List <String > revisedTxt = new ArrayList <>();
125+
126+ int old_ln = match .group (1 ) == null ? 1 : Integer .parseInt (match .group (1 ));
127+ int new_ln = match .group (3 ) == null ? 1 : Integer .parseInt (match .group (3 ));
128+
129+ while (this .READER .ready ()) {
130+ String line = READER .readLine ();
131+
132+ if (line .startsWith (" " ) || line .startsWith ("+" )) {
133+ revisedTxt .add (line .substring (1 ));
134+ }
135+ if (line .startsWith (" " ) || line .startsWith ("-" )) {
136+ originalTxt .add (line .substring (1 ));
137+ }
138+ if (line .equals ("" )) {
139+ break ;
140+ }
141+ }
142+
143+ } catch (IOException ex ) {
144+ Logger .getLogger (UnifiedDiffParser .class .getName ()).log (Level .SEVERE , null , ex );
145+ throw new UnifiedDiffParserException (ex );
146+ }
111147 }
112148
113149 public void processIndex (MatchResult match , String line ) {
@@ -116,6 +152,20 @@ public void processIndex(MatchResult match, String line) {
116152 actualFile .setIndex (line .substring (6 ));
117153 }
118154
155+ private void processFromFile (MatchResult match , String line ) {
156+ initFileIfNecessary ();
157+ actualFile .setFromFile (extractFileName (line ));
158+ }
159+
160+ private void processToFile (MatchResult match , String line ) {
161+ initFileIfNecessary ();
162+ actualFile .setToFile (extractFileName (line ));
163+ }
164+
165+ private String extractFileName (String line ) {
166+ return line .substring (4 ).replaceFirst ("^(a|b)\\ /" , "" );
167+ }
168+
119169 class UnifiedDiffLine {
120170
121171 private final Pattern pattern ;
@@ -132,7 +182,7 @@ public UnifiedDiffLine(boolean stopsHeaderParsing, String pattern, BiConsumer<Ma
132182 this .stopsHeaderParsing = stopsHeaderParsing ;
133183 }
134184
135- public boolean processLine (String line ) {
185+ public boolean processLine (String line ) throws UnifiedDiffParserException {
136186 Matcher m = pattern .matcher (line );
137187 if (m .find ()) {
138188 command .accept (m .toMatchResult (), line );
0 commit comments