001    package org.apache.maven.scm.provider.bazaar.command.changelog;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.maven.scm.ChangeFile;
023    import org.apache.maven.scm.ChangeSet;
024    import org.apache.maven.scm.ScmFileStatus;
025    import org.apache.maven.scm.log.ScmLogger;
026    import org.apache.maven.scm.provider.bazaar.command.BazaarConsumer;
027    
028    import java.util.ArrayList;
029    import java.util.Date;
030    import java.util.List;
031    
032    /**
033     * @author <a href="mailto:torbjorn@smorgrav.org">Torbjorn Eikli Smorgrav</a>
034     * @author Olivier Lamy
035     * @version $Id: BazaarChangeLogConsumer.java 1306867 2012-03-29 13:45:10Z olamy $
036     */
037    public class BazaarChangeLogConsumer
038        extends BazaarConsumer
039    {
040    
041        private static final String BAZAAR_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss Z";
042    
043        private static final String START_LOG_TAG = "-----";
044    
045        private static final String REVNO_TAG = "revno: ";
046    
047        private static final String AUTHOR_TAG = "committer: ";
048    
049        private static final String TIME_STAMP_TOKEN = "timestamp: ";
050    
051        private static final String MESSAGE_TOKEN = "message:";
052    
053        private static final String BRANCH_NICK_TOKEN = "branch nick: ";
054    
055        private static final String MERGED_TOKEN = "merged: ";
056    
057        private static final String RENAME_SEPARATOR = " => ";
058    
059        private List<ChangeSet> logEntries = new ArrayList<ChangeSet>();
060    
061        private ChangeSet currentChange;
062    
063        private ChangeSet lastChange;
064    
065        private boolean isMergeEntry;
066    
067        private String currentRevision;
068    
069        private StringBuilder currentComment;
070    
071        private String userDatePattern;
072    
073        /**
074         * Null means not parsing message nor files, UNKNOWN means parsing message
075         */
076        private ScmFileStatus currentStatus = null;
077    
078        public BazaarChangeLogConsumer( ScmLogger logger, String userDatePattern )
079        {
080            super( logger );
081    
082            this.userDatePattern = userDatePattern;
083        }
084    
085        public List<ChangeSet> getModifications()
086        {
087            return logEntries;
088        }
089    
090        /** {@inheritDoc} */
091        public void doConsume( ScmFileStatus status, String line )
092        {
093            String tmpLine = line;
094    
095            // Parse line
096            if ( line.startsWith( START_LOG_TAG ) )
097            {
098                //If last entry was part a merged entry
099                if ( isMergeEntry && lastChange != null )
100                {
101                    String comment = lastChange.getComment();
102                    comment += "\n[MAVEN]: Merged from " + currentChange.getAuthor();
103                    comment += "\n[MAVEN]:    " + currentChange.getDateFormatted();
104                    comment += "\n[MAVEN]:    " + currentChange.getComment();
105                    lastChange.setComment( comment );
106                }
107    
108                //Init a new changeset
109                currentChange = new ChangeSet();
110                currentChange.setFiles( new ArrayList<ChangeFile>() );
111                logEntries.add( currentChange );
112    
113                //Reset memeber vars
114                currentComment = new StringBuilder();
115                currentStatus = null;
116                currentRevision = "";
117                isMergeEntry = false;
118            }
119            else if ( line.startsWith( MERGED_TOKEN ) )
120            {
121                //This is part of lastChange and is not a separate log entry
122                isMergeEntry = true;
123                logEntries.remove( currentChange );
124                if ( logEntries.size() > 0 )
125                {
126                    lastChange = (ChangeSet) logEntries.get( logEntries.size() - 1 );
127                }
128                else
129                {
130                    if ( getLogger().isWarnEnabled() )
131                    {
132                        getLogger().warn( "First entry was unexpectedly a merged entry" );
133                    }
134                    lastChange = null;
135                }
136            }
137            else if ( line.startsWith( REVNO_TAG ) )
138            {
139                tmpLine = line.substring( REVNO_TAG.length() );
140                tmpLine = tmpLine.trim();
141                currentRevision = tmpLine;
142            }
143            else if ( line.startsWith( AUTHOR_TAG ) )
144            {
145                tmpLine = line.substring( AUTHOR_TAG.length() );
146                tmpLine = tmpLine.trim();
147                currentChange.setAuthor( tmpLine );
148            }
149            else if ( line.startsWith( TIME_STAMP_TOKEN ) )
150            {
151                tmpLine = line.substring( TIME_STAMP_TOKEN.length() + 3 );
152                tmpLine = tmpLine.trim();
153                Date date = parseDate( tmpLine, userDatePattern, BAZAAR_TIME_PATTERN );
154                currentChange.setDate( date );
155            }
156            else if ( line.startsWith( MESSAGE_TOKEN ) )
157            {
158                currentStatus = ScmFileStatus.UNKNOWN;
159            }
160            else if ( status != null )
161            {
162                currentStatus = status;
163            }
164            else if ( currentStatus == ScmFileStatus.UNKNOWN )
165            {
166                currentComment.append( line );
167                currentChange.setComment( currentComment.toString() );
168                currentComment.append( "\n" );
169            }
170            else if ( currentStatus != null )
171            {
172                tmpLine = tmpLine.trim();
173                final ChangeFile changeFile;
174                if ( currentStatus == ScmFileStatus.RENAMED )
175                {
176                    final String[] parts = tmpLine.split( RENAME_SEPARATOR );
177                    if ( parts.length != 2 )
178                    {
179                        changeFile = new ChangeFile( tmpLine, currentRevision );
180                    }
181                    else
182                    {
183                        changeFile = new ChangeFile( parts[1], currentRevision );
184                        changeFile.setOriginalName( parts[0] );
185                    }
186                }
187                else
188                {
189                    changeFile = new ChangeFile( tmpLine, currentRevision );
190                }
191                changeFile.setAction( currentStatus );
192                currentChange.addFile( changeFile );
193            }
194            else if ( line.startsWith( BRANCH_NICK_TOKEN ) )
195            {
196                //ignore
197            }
198            else
199            {
200                if ( getLogger().isWarnEnabled() )
201                {
202                    getLogger().warn( "Could not figure out of: " + line );
203                }
204            }
205        }
206    }