Author: olamy
Date: Wed Dec  7 21:08:29 2011
New Revision: 1211635

URL: http://svn.apache.org/viewvc?rev=1211635&view=rev
Log:
[SCM-649] Enhance SCM changelog model to hold more data about changes
patch regarding git implementation.
patch modified with using maven codestyle
Submitted by Petr Kozelka.

Modified:
    
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumer.java
    
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/test/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumerTest.java

Modified: 
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumer.java
URL: 
http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumer.java?rev=1211635&r1=1211634&r2=1211635&view=diff
==============================================================================
--- 
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumer.java
 (original)
+++ 
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumer.java
 Wed Dec  7 21:08:29 2011
@@ -19,18 +19,21 @@ package org.apache.maven.scm.provider.gi
  * under the License.
  */
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-
 import org.apache.maven.scm.ChangeFile;
 import org.apache.maven.scm.ChangeSet;
+import org.apache.maven.scm.ScmFileStatus;
 import org.apache.maven.scm.log.ScmLogger;
 import org.apache.maven.scm.util.AbstractConsumer;
 import org.apache.regexp.RE;
 import org.apache.regexp.RESyntaxException;
 
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
 /**
  * @author <a href="mailto:strub...@yahoo.de";>Mark Struberg</a>
  * @author Olivier Lamy
@@ -56,6 +59,26 @@ public class GitChangeLogConsumer
     private static final int STATUS_GET_AUTHOR = 2;
 
     /**
+     * State machine constant: expecting parent hash information
+     */
+    private static final int STATUS_RAW_TREE = 21;
+
+    /**
+     * State machine constant: expecting parent hash information
+     */
+    private static final int STATUS_RAW_PARENT = 22;
+
+    /**
+     * State machine constant: expecting author name, email and timestamp 
information
+     */
+    private static final int STATUS_RAW_AUTHOR = 23;
+
+    /**
+     * State machine constant: expecting committer name, email and timestamp 
information
+     */
+    private static final int STATUS_RAW_COMMITTER = 24;
+
+    /**
      * State machine constant: expecting date information
      */
     private static final int STATUS_GET_DATE = 3;
@@ -81,6 +104,26 @@ public class GitChangeLogConsumer
     private static final String AUTHOR_PATTERN = "^Author: (.*)";
 
     /**
+     * The pattern used to match git tree hash lines (raw mode)
+     */
+    private static final String RAW_TREE_PATTERN = "^tree ([:xdigit:]+)";
+
+    /**
+     * The pattern used to match git parent hash lines (raw mode)
+     */
+    private static final String RAW_PARENT_PATTERN = "^parent ([:xdigit:]+)";
+
+    /**
+     * The pattern used to match git author lines (raw mode)
+     */
+    private static final String RAW_AUTHOR_PATTERN = "^author (.+ <.+>) 
([:digit:]+) (.*)";
+
+    /**
+     * The pattern used to match git author lines (raw mode)
+     */
+    private static final String RAW_COMMITTER_PATTERN = "^committer (.+ <.+>) 
([:digit:]+) (.*)";
+
+    /**
      * The pattern used to match git date lines
      */
     private static final String DATE_PATTERN = "^Date:\\s*(.*)";
@@ -88,7 +131,8 @@ public class GitChangeLogConsumer
     /**
      * The pattern used to match git file lines
      */
-    private static final String FILE_PATTERN = "^:\\d* \\d* [:xdigit:]*\\.* 
[:xdigit:]*\\.* ([:upper:])\\t(.*)";
+    private static final String FILE_PATTERN =
+        "^:\\d* \\d* [:xdigit:]*\\.* [:xdigit:]*\\.* 
([:upper:])[:digit:]*\\t([^\\t]*)(\\t(.*))?";
 
     /**
      * Current status of the parser
@@ -126,6 +170,26 @@ public class GitChangeLogConsumer
     private RE authorRegexp;
 
     /**
+     * The regular expression used to match tree hash lines in raw mode
+     */
+    private RE rawTreeRegexp;
+
+    /**
+     * The regular expression used to match parent hash lines in raw mode
+     */
+    private RE rawParentRegexp;
+
+    /**
+     * The regular expression used to match author lines in raw mode
+     */
+    private RE rawAuthorRegexp;
+
+    /**
+     * The regular expression used to match committer lines in raw mode
+     */
+    private RE rawCommitterRegexp;
+
+    /**
      * The regular expression used to match date lines
      */
     private RE dateRegexp;
@@ -152,12 +216,16 @@ public class GitChangeLogConsumer
             authorRegexp = new RE( AUTHOR_PATTERN );
             dateRegexp = new RE( DATE_PATTERN );
             fileRegexp = new RE( FILE_PATTERN );
+            rawTreeRegexp = new RE( RAW_TREE_PATTERN );
+            rawParentRegexp = new RE( RAW_PARENT_PATTERN );
+            rawAuthorRegexp = new RE( RAW_AUTHOR_PATTERN );
+            rawCommitterRegexp = new RE( RAW_COMMITTER_PATTERN );
         }
         catch ( RESyntaxException ex )
         {
             throw new RuntimeException(
-                                        "INTERNAL ERROR: Could not create 
regexp to parse git log file. This shouldn't happen. Something is probably 
wrong with the oro installation.",
-                                        ex );
+                "INTERNAL ERROR: Could not create regexp to parse git log 
file. This shouldn't happen. Something is probably wrong with the oro 
installation.",
+                ex );
         }
     }
 
@@ -173,7 +241,9 @@ public class GitChangeLogConsumer
     // StreamConsumer Implementation
     // ----------------------------------------------------------------------
 
-    /** {@inheritDoc} */
+    /**
+     * {@inheritDoc}
+     */
     public void consumeLine( String line )
     {
         switch ( status )
@@ -193,6 +263,18 @@ public class GitChangeLogConsumer
             case STATUS_GET_FILE:
                 processGetFile( line );
                 break;
+            case STATUS_RAW_TREE:
+                processGetRawTree( line );
+                break;
+            case STATUS_RAW_PARENT:
+                processGetRawParent( line );
+                break;
+            case STATUS_RAW_AUTHOR:
+                processGetRawAuthor( line );
+                break;
+            case STATUS_RAW_COMMITTER:
+                processGetRawCommitter( line );
+                break;
             default:
                 throw new IllegalStateException( "Unknown state: " + status );
         }
@@ -235,6 +317,14 @@ public class GitChangeLogConsumer
      */
     private void processGetAuthor( String line )
     {
+        // this autodetects 'raw' format
+        if ( rawTreeRegexp.match( line ) )
+        {
+            status = STATUS_RAW_TREE;
+            processGetRawTree( line );
+            return;
+        }
+
         if ( !authorRegexp.match( line ) )
         {
             return;
@@ -247,6 +337,102 @@ public class GitChangeLogConsumer
     }
 
     /**
+     * Process the current input line in the STATUS_RAW_TREE state.  This
+     * state gathers tree hash part of a log entry.
+     *
+     * @param line a line of text from the git log output
+     */
+    private void processGetRawTree( String line )
+    {
+        if ( !rawTreeRegexp.match( line ) )
+        {
+            return;
+        }
+        //here we could set treeHash if it appears in the model: 
currentChange.setTreeHash( rawTreeRegexp.getParen( 1 ) );
+        status = STATUS_RAW_PARENT;
+    }
+
+    /**
+     * Process the current input line in the STATUS_RAW_PARENT state.  This
+     * state gathers parent revisions of a log entry.
+     *
+     * @param line a line of text from the git log output
+     */
+    private void processGetRawParent( String line )
+    {
+        if ( !rawParentRegexp.match( line ) )
+        {
+            status = STATUS_RAW_AUTHOR;
+            processGetRawAuthor( line );
+            return;
+        }
+        String parentHash = rawParentRegexp.getParen( 1 );
+
+        addParentRevision( parentHash );
+    }
+
+    /**
+     * In git log, both parent and merged revisions are called parent. 
Fortunately, the real parent comes first in the log.
+     * This method takes care of the difference.
+     *
+     * @param hash -
+     */
+    private void addParentRevision( String hash )
+    {
+        if ( currentChange.getParentRevision() == null )
+        {
+            currentChange.setParentRevision( hash );
+        }
+        else
+        {
+            currentChange.addMergedRevision( hash );
+        }
+    }
+
+    /**
+     * Process the current input line in the STATUS_RAW_AUTHOR state.  This
+     * state gathers all the author information of a log entry.
+     *
+     * @param line a line of text from the git log output
+     */
+    private void processGetRawAuthor( String line )
+    {
+        if ( !rawAuthorRegexp.match( line ) )
+        {
+            return;
+        }
+        String author = rawAuthorRegexp.getParen( 1 );
+        currentChange.setAuthor( author );
+
+        String datestring = rawAuthorRegexp.getParen( 2 );
+        String tz = rawAuthorRegexp.getParen( 3 );
+
+        // with --format=raw option (which gets us to this methods), date is 
always in seconds since beginning of time
+        // even explicit --date=iso is ignored, so we ignore both 
userDateFormat and GIT_TIMESTAMP_PATTERN here
+        Calendar c = Calendar.getInstance( TimeZone.getTimeZone( tz ) );
+        c.setTimeInMillis( Long.parseLong( datestring ) * 1000 );
+        currentChange.setDate( c.getTime() );
+
+        status = STATUS_RAW_COMMITTER;
+    }
+
+    /**
+     * Process the current input line in the STATUS_RAW_AUTHOR state.  This
+     * state gathers all the committer information of a log entry.
+     *
+     * @param line a line of text from the git log output
+     */
+    private void processGetRawCommitter( String line )
+    {
+        if ( !rawCommitterRegexp.match( line ) )
+        {
+            return;
+        }
+        // here we could set committer and committerDate, the same way as in 
processGetRawAuthor
+        status = STATUS_GET_COMMENT;
+    }
+
+    /**
      * Process the current input line in the STATUS_GET_DATE state.  This
      * state gathers all of the date information that are part of a log entry.
      *
@@ -326,12 +512,48 @@ public class GitChangeLogConsumer
             {
                 return;
             }
-            // String action = fileRegexp.getParen( 1 );
+            final String actionChar = fileRegexp.getParen( 1 );
             // action is currently not used
-
+            final ScmFileStatus action;
             String name = fileRegexp.getParen( 2 );
+            String originalName = null;
+            String originalRevision = null;
+            if ( "A".equals( actionChar ) )
+            {
+                action = ScmFileStatus.ADDED;
+            }
+            else if ( "M".equals( actionChar ) )
+            {
+                action = ScmFileStatus.MODIFIED;
+            }
+            else if ( "D".equals( actionChar ) )
+            {
+                action = ScmFileStatus.DELETED;
+            }
+            else if ( "R".equals( actionChar ) )
+            {
+                action = ScmFileStatus.RENAMED;
+                originalName = name;
+                name = fileRegexp.getParen( 4 );
+                originalRevision = currentChange.getParentRevision();
+            }
+            else if ( "C".equals( actionChar ) )
+            {
+                action = ScmFileStatus.COPIED;
+                originalName = name;
+                name = fileRegexp.getParen( 4 );
+                originalRevision = currentChange.getParentRevision();
+            }
+            else
+            {
+                action = ScmFileStatus.UNKNOWN;
+            }
 
-            currentChange.addFile( new ChangeFile( name, currentRevision ) );
+            final ChangeFile changeFile = new ChangeFile( name, 
currentRevision );
+            changeFile.setAction( action );
+            changeFile.setOriginalName( originalName );
+            changeFile.setOriginalRevision( originalRevision );
+            currentChange.addFile( changeFile );
         }
     }
 

Modified: 
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/test/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumerTest.java
URL: 
http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/test/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumerTest.java?rev=1211635&r1=1211634&r2=1211635&view=diff
==============================================================================
--- 
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/test/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumerTest.java
 (original)
+++ 
maven/scm/trunk/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gitexe/src/test/java/org/apache/maven/scm/provider/git/gitexe/command/changelog/GitChangeLogConsumerTest.java
 Wed Dec  7 21:08:29 2011
@@ -19,19 +19,24 @@ package org.apache.maven.scm.provider.gi
  * under the License.
  */
 
+import org.apache.maven.scm.ChangeFile;
+import org.apache.maven.scm.ChangeSet;
+import org.apache.maven.scm.ScmFileStatus;
+import org.apache.maven.scm.log.DefaultLog;
+import org.apache.regexp.RE;
+import org.codehaus.plexus.PlexusTestCase;
+import org.junit.Assert;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.text.SimpleDateFormat;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.TimeZone;
-
-import org.apache.maven.scm.ChangeFile;
-import org.apache.maven.scm.ChangeSet;
-import org.apache.maven.scm.log.DefaultLog;
-import org.apache.regexp.RE;
-import org.codehaus.plexus.PlexusTestCase;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * @author <a href="mailto:strub...@yahoo.de";>Mark Struberg</a>
@@ -39,7 +44,7 @@ import org.codehaus.plexus.PlexusTestCas
 public class GitChangeLogConsumerTest
     extends PlexusTestCase
 {
-    
+
     public void testConsumer1()
         throws Exception
     {
@@ -49,9 +54,9 @@ public class GitChangeLogConsumerTest
 
         boolean match = dateRegexp.match( "Date:   2007-11-24 01:13:10 +0100" 
);
         String datestring = dateRegexp.getParen( 1 );
-        assertEquals("2007-11-24 01:13:10 +0100", datestring);
+        assertEquals( "2007-11-24 01:13:10 +0100", datestring );
         assertTrue( match );
-        
+
         GitChangeLogConsumer consumer = new GitChangeLogConsumer( new 
DefaultLog(), null );
 
         File f = getTestFile( 
"/src/test/resources/git/changelog/gitwhatchanged.gitlog" );
@@ -123,6 +128,9 @@ public class GitChangeLogConsumerTest
 
         List<ChangeSet> modifications = consumer.getModifications();
 
+        // must use *Linked* HashMap to have predictable toString
+        final Map<ScmFileStatus, AtomicInteger> summary = new 
LinkedHashMap<ScmFileStatus, AtomicInteger>();
+
         for ( Iterator<ChangeSet> i = modifications.iterator(); i.hasNext(); )
         {
             ChangeSet entry = i.next();
@@ -137,7 +145,19 @@ public class GitChangeLogConsumerTest
 
             assertNotNull( entry.getFiles() );
             assertFalse( entry.getFiles().isEmpty() );
+
+            for ( ChangeFile file : entry.getFiles() )
+            {
+                final ScmFileStatus action = file.getAction();
+                if ( !summary.containsKey( action ) )
+                {
+                    summary.put( action, new AtomicInteger() );
+                }
+                summary.get( action ).incrementAndGet();
+            }
         }
+        Assert.assertEquals( "Action summary differs from expectations", 
"{modified=21, added=88, deleted=1}",
+                             summary.toString() );
 
         assertEquals( 8, modifications.size() );
 
@@ -153,8 +173,8 @@ public class GitChangeLogConsumerTest
 
         assertEquals( "52733aa427041cafd760833cb068ffe897fd35db", 
entry.getRevision() );
 
-        assertEquals( "fixed a GitCommandLineUtil and provice first version of 
the checkin command.", entry
-            .getComment() );
+        assertEquals( "fixed a GitCommandLineUtil and provice first version of 
the checkin command.",
+                      entry.getComment() );
 
         assertNotNull( entry.getFiles() );
 
@@ -162,9 +182,9 @@ public class GitChangeLogConsumerTest
 
         ChangeFile cf = (ChangeFile) entry.getFiles().get( 0 );
         assertEquals(
-                      
"maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/GitCommandLineUtils.java",
-                      cf.getName() );
+            
"maven-scm-provider-gitexe/src/main/java/org/apache/maven/scm/provider/git/gitexe/command/GitCommandLineUtils.java",
+            cf.getName() );
         assertTrue( cf.getRevision() != null && cf.getRevision().length() > 0 
);
     }
- 
+
 }


Reply via email to