|
|
@@ -14,15 +14,9 @@ import java.io.IOException; |
|
|
|
import java.io.OutputStreamWriter; |
|
|
|
import java.io.PrintWriter; |
|
|
|
import java.io.UnsupportedEncodingException; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.Date; |
|
|
|
import java.util.Enumeration; |
|
|
|
import java.util.Hashtable; |
|
|
|
import java.util.Iterator; |
|
|
|
import java.util.Properties; |
|
|
|
import java.util.Vector; |
|
|
|
import org.apache.aut.nativelib.ExecOutputHandler; |
|
|
|
import org.apache.avalon.excalibur.i18n.ResourceManager; |
|
|
|
import org.apache.avalon.excalibur.i18n.Resources; |
|
|
|
import org.apache.avalon.excalibur.io.IOUtil; |
|
|
@@ -63,33 +57,15 @@ import org.apache.tools.todo.types.Commandline; |
|
|
|
*/ |
|
|
|
public class ChangeLog |
|
|
|
extends AbstractTask |
|
|
|
implements ExecOutputHandler |
|
|
|
{ |
|
|
|
private final static Resources REZ = |
|
|
|
ResourceManager.getPackageResources( ChangeLog.class ); |
|
|
|
|
|
|
|
//private static final int GET_ENTRY = 0; |
|
|
|
private static final int GET_FILE = 1; |
|
|
|
private static final int GET_DATE = 2; |
|
|
|
private static final int GET_COMMENT = 3; |
|
|
|
private static final int GET_REVISION = 4; |
|
|
|
private static final int GET_PREVIOUS_REV = 5; |
|
|
|
|
|
|
|
/** input format for dates read in from cvs log */ |
|
|
|
private static final SimpleDateFormat c_inputDate = new SimpleDateFormat( "yyyy/MM/dd" ); |
|
|
|
/** output format for dates writtn to xml file */ |
|
|
|
private static final SimpleDateFormat c_outputDate = new SimpleDateFormat( "yyyy-MM-dd" ); |
|
|
|
/** output format for times writtn to xml file */ |
|
|
|
private static final SimpleDateFormat c_outputTime = new SimpleDateFormat( "hh:mm" ); |
|
|
|
|
|
|
|
/** User list */ |
|
|
|
private File m_users; |
|
|
|
|
|
|
|
/** User list */ |
|
|
|
private final Properties m_userList = new Properties(); |
|
|
|
private File m_usersFile; |
|
|
|
|
|
|
|
/** User list */ |
|
|
|
private Vector m_ulist = new Vector(); |
|
|
|
private Vector m_cvsUsers = new Vector(); |
|
|
|
|
|
|
|
/** Input dir */ |
|
|
|
private File m_basedir; |
|
|
@@ -97,17 +73,6 @@ public class ChangeLog |
|
|
|
/** Output file */ |
|
|
|
private File m_destfile; |
|
|
|
|
|
|
|
private int m_status = GET_FILE; |
|
|
|
|
|
|
|
/** rcs entries */ |
|
|
|
private final Hashtable m_entries = new Hashtable(); |
|
|
|
private String m_workingFile; |
|
|
|
private String m_workingDate; |
|
|
|
private String m_workingAuthor; |
|
|
|
private String m_workingComment; |
|
|
|
private String m_workingRevision; |
|
|
|
private String m_workingPreviousRevision; |
|
|
|
|
|
|
|
/** |
|
|
|
* Set the base dir for cvs. |
|
|
|
*/ |
|
|
@@ -127,9 +92,9 @@ public class ChangeLog |
|
|
|
/** |
|
|
|
* Set a lookup list of user names & addresses |
|
|
|
*/ |
|
|
|
public void setUserlist( final File users ) |
|
|
|
public void setUsersfile( final File usersFile ) |
|
|
|
{ |
|
|
|
m_users = users; |
|
|
|
m_usersFile = usersFile; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@@ -139,7 +104,7 @@ public class ChangeLog |
|
|
|
*/ |
|
|
|
public void addUser( final CvsUser user ) |
|
|
|
{ |
|
|
|
m_ulist.addElement( user ); |
|
|
|
m_cvsUsers.addElement( user ); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@@ -149,26 +114,29 @@ public class ChangeLog |
|
|
|
{ |
|
|
|
validate(); |
|
|
|
|
|
|
|
loadUserlist(); |
|
|
|
final Properties userList = new Properties(); |
|
|
|
|
|
|
|
loadUserlist( userList ); |
|
|
|
|
|
|
|
for( Enumeration e = m_ulist.elements(); e.hasMoreElements(); ) |
|
|
|
for( Enumeration e = m_cvsUsers.elements(); e.hasMoreElements(); ) |
|
|
|
{ |
|
|
|
final CvsUser user = (CvsUser)e.nextElement(); |
|
|
|
user.validate(); |
|
|
|
m_userList.put( user.getUserID(), user.getDisplayname() ); |
|
|
|
userList.put( user.getUserID(), user.getDisplayname() ); |
|
|
|
} |
|
|
|
|
|
|
|
final Commandline command = new Commandline(); |
|
|
|
command.setExecutable( "cvs" ); |
|
|
|
command.addArgument( "log" ); |
|
|
|
|
|
|
|
final ChangeLogParser parser = new ChangeLogParser( userList ); |
|
|
|
final Execute exe = new Execute(); |
|
|
|
exe.setWorkingDirectory( m_basedir ); |
|
|
|
exe.setCommandline( command ); |
|
|
|
exe.setExecOutputHandler( this ); |
|
|
|
exe.setExecOutputHandler( parser ); |
|
|
|
exe.execute( getContext() ); |
|
|
|
|
|
|
|
writeChangeLog(); |
|
|
|
writeChangeLog( parser ); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@@ -195,10 +163,10 @@ public class ChangeLog |
|
|
|
REZ.getString( "changelog.bad-basedir.error", m_basedir.getAbsolutePath() ); |
|
|
|
throw new TaskException( message ); |
|
|
|
} |
|
|
|
if( null != m_users && !m_users.exists() ) |
|
|
|
if( null != m_usersFile && !m_usersFile.exists() ) |
|
|
|
{ |
|
|
|
final String message = |
|
|
|
REZ.getString( "changelog.bad-userlist.error", m_users.getAbsolutePath() ); |
|
|
|
REZ.getString( "changelog.bad-userlist.error", m_usersFile.getAbsolutePath() ); |
|
|
|
throw new TaskException( message ); |
|
|
|
} |
|
|
|
} |
|
|
@@ -209,14 +177,14 @@ public class ChangeLog |
|
|
|
* |
|
|
|
* @throws TaskException if file can not be loaded for some reason |
|
|
|
*/ |
|
|
|
private void loadUserlist() |
|
|
|
private void loadUserlist( final Properties userList ) |
|
|
|
throws TaskException |
|
|
|
{ |
|
|
|
if( null != m_users ) |
|
|
|
if( null != m_usersFile ) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
m_userList.load( new FileInputStream( m_users ) ); |
|
|
|
userList.load( new FileInputStream( m_usersFile ) ); |
|
|
|
} |
|
|
|
catch( final IOException ioe ) |
|
|
|
{ |
|
|
@@ -225,187 +193,12 @@ public class ChangeLog |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Receive notification about the process writing |
|
|
|
* to standard output. |
|
|
|
*/ |
|
|
|
public void stdout( final String line ) |
|
|
|
{ |
|
|
|
switch( m_status ) |
|
|
|
{ |
|
|
|
case GET_FILE: |
|
|
|
processFile( line ); |
|
|
|
break; |
|
|
|
case GET_REVISION: |
|
|
|
processRevision( line ); |
|
|
|
//Was a fall through .... |
|
|
|
//break; |
|
|
|
case GET_DATE: |
|
|
|
processDate( line ); |
|
|
|
break; |
|
|
|
|
|
|
|
case GET_COMMENT: |
|
|
|
processComment( line ); |
|
|
|
break; |
|
|
|
|
|
|
|
case GET_PREVIOUS_REV: |
|
|
|
processGetPreviousRevision( line ); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Process a line while in "GET_COMMENT" state. |
|
|
|
* |
|
|
|
* @param line the line |
|
|
|
*/ |
|
|
|
private void processComment( final String line ) |
|
|
|
{ |
|
|
|
final String lineSeparator = System.getProperty( "line.separator" ); |
|
|
|
if( line.startsWith( "======" ) || line.startsWith( "------" ) ) |
|
|
|
{ |
|
|
|
final int end = m_workingComment.length() - lineSeparator.length(); //was -1 |
|
|
|
m_workingComment = m_workingComment.substring( 0, end ); |
|
|
|
m_workingComment = "<![CDATA[" + m_workingComment + "]]>"; |
|
|
|
m_status = GET_PREVIOUS_REV; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
m_workingComment += line + lineSeparator; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Process a line while in "GET_FILE" state. |
|
|
|
* |
|
|
|
* @param line the line |
|
|
|
*/ |
|
|
|
private void processFile( final String line ) |
|
|
|
{ |
|
|
|
if( line.startsWith( "Working file:" ) ) |
|
|
|
{ |
|
|
|
m_workingFile = line.substring( 14, line.length() ); |
|
|
|
m_status = GET_REVISION; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Process a line while in "REVISION" state. |
|
|
|
* |
|
|
|
* @param line the line |
|
|
|
*/ |
|
|
|
private void processRevision( final String line ) |
|
|
|
{ |
|
|
|
if( line.startsWith( "revision" ) ) |
|
|
|
{ |
|
|
|
m_workingRevision = line.substring( 9 ); |
|
|
|
m_status = GET_DATE; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Process a line while in "DATE" state. |
|
|
|
* |
|
|
|
* @param line the line |
|
|
|
*/ |
|
|
|
private void processDate( final String line ) |
|
|
|
{ |
|
|
|
if( line.startsWith( "date:" ) ) |
|
|
|
{ |
|
|
|
m_workingDate = line.substring( 6, 16 ); |
|
|
|
String lineData = line.substring( line.indexOf( ";" ) + 1 ); |
|
|
|
m_workingAuthor = lineData.substring( 10, lineData.indexOf( ";" ) ); |
|
|
|
|
|
|
|
if( m_userList.containsKey( m_workingAuthor ) ) |
|
|
|
{ |
|
|
|
m_workingAuthor = "<![CDATA[" + m_userList.getProperty( m_workingAuthor ) + "]]>"; |
|
|
|
} |
|
|
|
|
|
|
|
m_status = GET_COMMENT; |
|
|
|
|
|
|
|
//Reset comment to empty here as we can accumulate multiple lines |
|
|
|
//in the processComment method |
|
|
|
m_workingComment = ""; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Process a line while in "GET_PREVIOUS_REVISION" state. |
|
|
|
* |
|
|
|
* @param line the line |
|
|
|
*/ |
|
|
|
private void processGetPreviousRevision( final String line ) |
|
|
|
{ |
|
|
|
final String entryKey = m_workingDate + m_workingAuthor + m_workingComment; |
|
|
|
if( line.startsWith( "revision" ) ) |
|
|
|
{ |
|
|
|
m_workingPreviousRevision = line.substring( 9 ); |
|
|
|
m_status = GET_FILE; |
|
|
|
|
|
|
|
CVSEntry entry; |
|
|
|
if( !m_entries.containsKey( entryKey ) ) |
|
|
|
{ |
|
|
|
entry = new CVSEntry( parseDate( m_workingDate ), m_workingAuthor, m_workingComment ); |
|
|
|
m_entries.put( entryKey, entry ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
entry = (CVSEntry)m_entries.get( entryKey ); |
|
|
|
} |
|
|
|
entry.addFile( m_workingFile, m_workingRevision, m_workingPreviousRevision ); |
|
|
|
} |
|
|
|
else if( line.startsWith( "======" ) ) |
|
|
|
{ |
|
|
|
m_status = GET_FILE; |
|
|
|
CVSEntry entry; |
|
|
|
if( !m_entries.containsKey( entryKey ) ) |
|
|
|
{ |
|
|
|
entry = new CVSEntry( parseDate( m_workingDate ), m_workingAuthor, m_workingComment ); |
|
|
|
m_entries.put( entryKey, entry ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
entry = (CVSEntry)m_entries.get( entryKey ); |
|
|
|
} |
|
|
|
entry.addFile( m_workingFile, m_workingRevision ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Receive notification about the process writing |
|
|
|
* to standard error. |
|
|
|
*/ |
|
|
|
public void stderr( String line ) |
|
|
|
{ |
|
|
|
//ignored |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Parse date out from expected format. |
|
|
|
* |
|
|
|
* @param date the string holding dat |
|
|
|
* @return the date object or null if unknown date format |
|
|
|
*/ |
|
|
|
private Date parseDate( final String date ) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
return c_inputDate.parse( date ); |
|
|
|
} |
|
|
|
catch( ParseException e ) |
|
|
|
{ |
|
|
|
final String message = REZ.getString( "changelog.bat-date.error", date ); |
|
|
|
getContext().error( message ); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Print changelog to file specified in task. |
|
|
|
* |
|
|
|
* @throws TaskException if theres an error writing changelog |
|
|
|
*/ |
|
|
|
private void writeChangeLog() |
|
|
|
private void writeChangeLog( final ChangeLogParser parser ) |
|
|
|
throws TaskException |
|
|
|
{ |
|
|
|
FileOutputStream output = null; |
|
|
@@ -414,7 +207,10 @@ public class ChangeLog |
|
|
|
output = new FileOutputStream( m_destfile ); |
|
|
|
final PrintWriter writer = |
|
|
|
new PrintWriter( new OutputStreamWriter( output, "UTF-8" ) ); |
|
|
|
printChangeLog( writer ); |
|
|
|
|
|
|
|
final CVSEntry[] entrySet = parser.getEntrySetAsArray(); |
|
|
|
ChangeLogWriter serializer = new ChangeLogWriter(); |
|
|
|
serializer.printChangeLog( writer, entrySet ); |
|
|
|
} |
|
|
|
catch( final UnsupportedEncodingException uee ) |
|
|
|
{ |
|
|
@@ -429,52 +225,4 @@ public class ChangeLog |
|
|
|
IOUtil.shutdownStream( output ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Print out the full changelog. |
|
|
|
*/ |
|
|
|
private void printChangeLog( final PrintWriter output ) |
|
|
|
{ |
|
|
|
output.println( "<changelog>" ); |
|
|
|
for( Enumeration en = m_entries.elements(); en.hasMoreElements(); ) |
|
|
|
{ |
|
|
|
final CVSEntry entry = (CVSEntry)en.nextElement(); |
|
|
|
printEntry( output, entry ); |
|
|
|
} |
|
|
|
output.println( "</changelog>" ); |
|
|
|
output.flush(); |
|
|
|
output.close(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Print out an individual entry in changelog. |
|
|
|
* |
|
|
|
* @param entry the entry to print |
|
|
|
*/ |
|
|
|
private void printEntry( final PrintWriter output, final CVSEntry entry ) |
|
|
|
{ |
|
|
|
output.println( "\t<entry>" ); |
|
|
|
output.println( "\t\t<date>" + c_outputDate.format( entry.getDate() ) + "</date>" ); |
|
|
|
output.println( "\t\t<time>" + c_outputTime.format( entry.getDate() ) + "</time>" ); |
|
|
|
output.println( "\t\t<author>" + entry.getAuthor() + "</author>" ); |
|
|
|
|
|
|
|
final Iterator iterator = entry.getFiles().iterator(); |
|
|
|
while( iterator.hasNext() ) |
|
|
|
{ |
|
|
|
final RCSFile file = (RCSFile)iterator.next(); |
|
|
|
output.println( "\t\t<file>" ); |
|
|
|
output.println( "\t\t\t<name>" + file.getName() + "</name>" ); |
|
|
|
output.println( "\t\t\t<revision>" + file.getRevision() + "</revision>" ); |
|
|
|
|
|
|
|
final String previousRevision = file.getPreviousRevision(); |
|
|
|
if( previousRevision != null ) |
|
|
|
{ |
|
|
|
output.println( "\t\t\t<prevrevision>" + previousRevision + "</prevrevision>" ); |
|
|
|
} |
|
|
|
|
|
|
|
output.println( "\t\t</file>" ); |
|
|
|
} |
|
|
|
output.println( "\t\t<msg>" + entry.getComment() + "</msg>" ); |
|
|
|
output.println( "\t</entry>" ); |
|
|
|
} |
|
|
|
} |