3939public final class UnifiedDiffReader {
4040
4141static final Pattern UNIFIED_DIFF_CHUNK_REGEXP =Pattern .compile ("^@@\\ s+-(?:(\\ d+)(?:,(\\ d+))?)\\ s+\\ +(?:(\\ d+)(?:,(\\ d+))?)\\ s+@@" );
42+ static final Pattern TIMESTAMP_REGEXP =Pattern .compile ("(\\ d{4}-\\ d{2}-\\ d{2}[T ]\\ d{2}:\\ d{2}:\\ d{2}\\ .\\ d{3,})" );
4243
4344private final InternalUnifiedDiffReader READER ;
4445private final UnifiedDiff data =new UnifiedDiff ();
@@ -49,9 +50,9 @@ public final class UnifiedDiffReader {
4950private final UnifiedDiffLine TO_FILE =new UnifiedDiffLine (true ,"^\\ +\\ +\\ +\\ s" ,this ::processToFile );
5051
5152private final UnifiedDiffLine CHUNK =new UnifiedDiffLine (false ,UNIFIED_DIFF_CHUNK_REGEXP ,this ::processChunk );
52- private final UnifiedDiffLine LINE_NORMAL =new UnifiedDiffLine ("^\\ s+ " ,this ::processNormalLine );
53+ private final UnifiedDiffLine LINE_NORMAL =new UnifiedDiffLine ("^\\ s" ,this ::processNormalLine );
5354private final UnifiedDiffLine LINE_DEL =new UnifiedDiffLine ("^-" ,this ::processDelLine );
54- private final UnifiedDiffLine LINE_ADD =new UnifiedDiffLine ("^+" ,this ::processAddLine );
55+ private final UnifiedDiffLine LINE_ADD =new UnifiedDiffLine ("^\\ +" ,this ::processAddLine );
5556
5657private UnifiedDiffFile actualFile ;
5758
@@ -81,20 +82,37 @@ private UnifiedDiff parse() throws IOException, UnifiedDiffParserException {
8182
8283while (line !=null ) {
8384if (!CHUNK .validLine (line )) {
84- processLine (line ,DIFF_COMMAND ,INDEX ,FROM_FILE ,TO_FILE );
85- }else {
86- processLine (line ,CHUNK );
85+ initFileIfNecessary ();
86+ while (!CHUNK .validLine (line )) {
87+ if (processLine (line ,DIFF_COMMAND ,INDEX ,FROM_FILE ,TO_FILE ) ==false ) {
88+ throw new UnifiedDiffParserException ("expected file start line not found" );
89+ }
90+ line =READER .readLine ();
91+ }
92+ }
93+ processLine (line ,CHUNK );
94+ while ((line =READER .readLine ()) !=null ) {
95+ if (processLine (line ,LINE_NORMAL ,LINE_ADD ,LINE_DEL ) ==false ) {
96+ throw new UnifiedDiffParserException ("expected data line not found" );
97+ }
98+ if (originalTxt .size () ==old_size &&revisedTxt .size () ==new_size ) {
99+ finalizeChunk ();
100+ break ;
101+ }
87102 }
88103line =READER .readLine ();
104+ if (line ==null ||line .startsWith ("--" )) {
105+ break ;
106+ }
89107 }
90108
91- finalizeChunk ();
92-
93- String tailTxt ="" ;
94- while (READER .ready ()) {
95- tailTxt +=READER .readLine () +"\n " ;
109+ if (READER .ready ()) {
110+ String tailTxt ="" ;
111+ while (READER .ready ()) {
112+ tailTxt +=READER .readLine () +"\n " ;
113+ }
114+ data .setTailTxt (tailTxt );
96115 }
97- data .setTailTxt (tailTxt );
98116
99117return data ;
100118 }
@@ -114,30 +132,31 @@ public static UnifiedDiff parseUnifiedDiff(InputStream stream) throws IOExceptio
114132return parser .parse ();
115133 }
116134
117- private void processLine (String line ,UnifiedDiffLine ...rules )throws UnifiedDiffParserException {
135+ private boolean processLine (String line ,UnifiedDiffLine ...rules )throws UnifiedDiffParserException {
118136for (UnifiedDiffLine rule :rules ) {
119137if (rule .processLine (line )) {
120138LOG .info (" >>> processed rule " +rule .toString ());
121- return ;
139+ return true ;
122140 }
123141 }
124142LOG .info (" >>> no rule matched " +line );
125- throw new UnifiedDiffParserException ("parsing error at line " +line );
143+ return false ;
144+ //throw new UnifiedDiffParserException("parsing error at line " + line);
126145 }
127146
128147private void initFileIfNecessary () {
129148if (!originalTxt .isEmpty () || !revisedTxt .isEmpty ()) {
130- finalizeChunk ();
131- actualFile =null ;
149+ throw new IllegalStateException ();
132150 }
151+ actualFile =null ;
133152if (actualFile ==null ) {
134153actualFile =new UnifiedDiffFile ();
135154data .addFile (actualFile );
136155 }
137156 }
138157
139158private void processDiff (MatchResult match ,String line ) {
140- initFileIfNecessary ();
159+ // initFileIfNecessary();
141160LOG .log (Level .INFO ,"start {0}" ,line );
142161String []fromTo =parseFileNames (READER .lastLine ());
143162actualFile .setFromFile (fromTo [0 ]);
@@ -181,7 +200,7 @@ private void processDelLine(MatchResult match, String line) {
181200 }
182201
183202private void processChunk (MatchResult match ,String chunkStart ) {
184- finalizeChunk ();
203+ // finalizeChunk();
185204old_ln =toInteger (match ,1 ,1 );
186205old_size =toInteger (match ,2 ,0 );
187206new_ln =toInteger (match ,3 ,1 );
@@ -195,27 +214,43 @@ private void processChunk(MatchResult match, String chunkStart) {
195214 }
196215
197216private static Integer toInteger (MatchResult match ,int group ,int defValue )throws NumberFormatException {
198- return Integer .valueOf (Objects .toString (match .group (group ) ,"" +defValue ));
217+ return Integer .valueOf (Objects .toString (match .group (group ),"" +defValue ));
199218 }
200219
201220private void processIndex (MatchResult match ,String line ) {
202- initFileIfNecessary ();
221+ // initFileIfNecessary();
203222LOG .log (Level .INFO ,"index {0}" ,line );
204223actualFile .setIndex (line .substring (6 ));
205224 }
206225
207226private void processFromFile (MatchResult match ,String line ) {
208- initFileIfNecessary ();
227+ // initFileIfNecessary();
209228actualFile .setFromFile (extractFileName (line ));
229+ actualFile .setFromTimestamp (extractTimestamp (line ));
210230 }
211231
212232private void processToFile (MatchResult match ,String line ) {
213- initFileIfNecessary ();
233+ // initFileIfNecessary();
214234actualFile .setToFile (extractFileName (line ));
235+ actualFile .setToTimestamp (extractTimestamp (line ));
236+ }
237+
238+ private String extractFileName (String _line ) {
239+ Matcher matcher =TIMESTAMP_REGEXP .matcher (_line );
240+ String line =_line ;
241+ if (matcher .find ()) {
242+ line =line .substring (1 ,matcher .start ());
243+ }
244+ return line .substring (4 ).replaceFirst ("^(a|b)\\ /" ,"" )
245+ .replace (TIMESTAMP_REGEXP .toString (),"" ).trim ();
215246 }
216247
217- private String extractFileName (String line ) {
218- return line .substring (4 ).replaceFirst ("^(a|b)\\ /" ,"" );
248+ private String extractTimestamp (String line ) {
249+ Matcher matcher =TIMESTAMP_REGEXP .matcher (line );
250+ if (matcher .find ()) {
251+ return matcher .group ();
252+ }
253+ return null ;
219254 }
220255
221256final class UnifiedDiffLine {