2020/*
2121 * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
2222 * Portions Copyright (c) 2017, Chris Fraire <cfraire@me.com>.
23+ * Portions Copyright (c) 2020, Ric Harris <harrisric@users.noreply.github.com>.
2324 */
2425package org .opengrok .indexer .history ;
2526
3031import java .io .InputStream ;
3132import java .text .ParseException ;
3233import java .util .ArrayList ;
34+ import java .util .HashSet ;
3335import java .util .List ;
36+ import java .util .Set ;
3437import java .util .logging .Level ;
3538import java .util .logging .Logger ;
39+
3640import javax .xml .parsers .SAXParser ;
3741import javax .xml .parsers .SAXParserFactory ;
42+
3843import org .opengrok .indexer .configuration .RuntimeEnvironment ;
3944import org .opengrok .indexer .logger .LoggerFactory ;
4045import org .opengrok .indexer .util .Executor ;
@@ -56,13 +61,20 @@ class SubversionHistoryParser implements Executor.StreamHandler {
5661
5762 private static class Handler extends DefaultHandler2 {
5863
64+ /**
65+ * Example of the longest date format that we should accept - SimpleDateFormat cannot cope with micro/nano seconds.
66+ */
67+ static final int SVN_MILLIS_DATE_LENGTH = "2020-03-26T15:38:55.999Z" .length ();
68+
5969 final String prefix ;
6070 final String home ;
6171 final int length ;
62- final List <HistoryEntry > entries = new ArrayList <HistoryEntry >();
72+ final List <HistoryEntry > entries = new ArrayList <>();
73+ final Set <String > renamedFiles = new HashSet <>();
6374 final SubversionRepository repository ;
6475 HistoryEntry entry ;
6576 StringBuilder sb ;
77+ boolean isRenamed ;
6678
6779 Handler (String home , String prefix , int length , SubversionRepository repository ) {
6880 this .home = home ;
@@ -72,12 +84,19 @@ private static class Handler extends DefaultHandler2 {
7284 sb = new StringBuilder ();
7385 }
7486
87+ List <String > getRenamedFiles () {
88+ return new ArrayList <>(renamedFiles );
89+ }
90+
7591 @ Override
7692 public void startElement (String uri , String localName , String qname , Attributes attr ) {
93+ isRenamed = false ;
7794 if ("logentry" .equals (qname )) {
7895 entry = new HistoryEntry ();
7996 entry .setActive (true );
8097 entry .setRevision (attr .getValue ("revision" ));
98+ } else if ("path" .equals (qname )) {
99+ isRenamed = attr .getIndex ("copyfrom-path" ) != -1 ;
81100 }
82101 sb .setLength (0 );
83102 }
@@ -89,7 +108,13 @@ public void endElement(String uri, String localName, String qname) throws SAXExc
89108 entry .setAuthor (s );
90109 } else if ("date" .equals (qname )) {
91110 try {
92- entry .setDate (repository .parse (s ));
111+ // need to strip microseconds off - assume final character is Z otherwise invalid anyway.
112+ String dateString = s ;
113+ if (s .length () > SVN_MILLIS_DATE_LENGTH ) {
114+ dateString = dateString .substring (0 , SVN_MILLIS_DATE_LENGTH - 1 ) +
115+ dateString .charAt (dateString .length () - 1 );
116+ }
117+ entry .setDate (repository .parse (dateString ));
93118 } catch (ParseException ex ) {
94119 throw new SAXException ("Failed to parse date: " + s , ex );
95120 }
@@ -104,6 +129,9 @@ public void endElement(String uri, String localName, String qname) throws SAXExc
104129 // The same file names may be repeated in many commits,
105130 // so intern them to reduce the memory footprint.
106131 entry .addFile (path .intern ());
132+ if (isRenamed ) {
133+ renamedFiles .add (file .getAbsolutePath ().substring (home .length () + 1 ));
134+ }
107135 } else {
108136 LOGGER .log (Level .FINER , "Skipping file outside repository: " + s );
109137 }
@@ -177,7 +205,7 @@ History parse(File file, SubversionRepository repos, String sinceRevision,
177205 repos .removeAndVerifyOldestChangeset (entries , sinceRevision );
178206 }
179207
180- return new History (entries );
208+ return new History (entries , handler . getRenamedFiles () );
181209 }
182210
183211 /**
@@ -206,6 +234,6 @@ public void processStream(InputStream input) throws IOException {
206234 History parse (String buffer ) throws IOException {
207235 handler = new Handler ("/" , "" , 0 , new SubversionRepository ());
208236 processStream (new ByteArrayInputStream (buffer .getBytes ("UTF-8" )));
209- return new History (handler .entries );
237+ return new History (handler .entries , handler . getRenamedFiles () );
210238 }
211239}
0 commit comments