001    package org.apache.maven.scm.provider.hg.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 java.util.ArrayList;
023    import java.util.Date;
024    import java.util.List;
025    import java.util.Locale;
026    
027    import org.apache.maven.scm.ChangeFile;
028    import org.apache.maven.scm.ChangeSet;
029    import org.apache.maven.scm.ScmFileStatus;
030    import org.apache.maven.scm.log.ScmLogger;
031    import org.apache.maven.scm.provider.hg.command.HgConsumer;
032    
033    /**
034     * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
035     * @version $Id: HgChangeLogConsumer.java 1352832 2012-06-22 10:22:25Z olamy $
036     */
037    public class HgChangeLogConsumer
038        extends HgConsumer
039    {
040    
041        private static final String TIME_PATTERN = "yyyy-MM-dd HH:mm:ss Z";
042    
043        private static final String REVNO_TAG = "changeset: ";
044    
045        private static final String TAG_TAG = "tag:         ";
046    
047        private static final String AUTHOR_TAG = "user: ";
048    
049        private static final String TIME_STAMP_TOKEN = "date: ";
050    
051        private static final String MESSAGE_TOKEN = "description:";
052    
053        private static final String FILES_TOKEN = "files: ";
054    
055        private String prevLine = "";
056    
057        private String prevPrevLine = "";
058    
059        private List<ChangeSet> logEntries = new ArrayList<ChangeSet>();
060    
061        private ChangeSet currentChange;
062    
063        private String currentRevision;
064    
065        @SuppressWarnings( "unused" )
066        private String currentTag; // don't know what to do with this
067    
068        private String userDatePattern;
069    
070        private boolean spoolingComments;
071    
072        private List<String> currentComment = null;
073    
074        public HgChangeLogConsumer( ScmLogger logger, String userDatePattern )
075        {
076            super( logger );
077    
078            this.userDatePattern = userDatePattern;
079        }
080    
081        public List<ChangeSet> getModifications()
082        {
083            return logEntries;
084        }
085    
086        /** {@inheritDoc} */
087        public void consumeLine( String line )
088        {
089    
090            // override default behaviour which tries to pick through things for some standard messages.  that
091            // does not apply here
092            doConsume( null, line );
093        }
094    
095        /** {@inheritDoc} */
096        public void doConsume( ScmFileStatus status, String line )
097        {
098            String tmpLine = line;
099            // If current status == null then this is a new entry
100            // If the line == "" and previous line was "", then this is also a new entry
101            if ( ( line.equals( "" ) && ( prevLine.equals( "" ) && prevPrevLine.equals( "" ) ) ) || currentComment == null )
102            {
103                if ( currentComment != null )
104                {
105                    StringBuilder comment = new StringBuilder();
106                    for ( int i = 0; i < currentComment.size() - 1; i++ )
107                    {
108                        comment.append( currentComment.get( i ) );
109                        if ( i + 1 < currentComment.size() - 1 )
110                        {
111                            comment.append( '\n' );
112                        }
113                    }
114                    currentChange.setComment( comment.toString() );
115    
116                }
117    
118                spoolingComments = false;
119    
120                //Init a new changeset
121                currentChange = new ChangeSet();
122                currentChange.setFiles( new ArrayList<ChangeFile>( 0 ) );
123                logEntries.add( currentChange );
124    
125                //Reset memeber vars
126                currentComment = new ArrayList<String>();
127                currentRevision = "";
128            }
129    
130            if ( spoolingComments )
131            {
132                currentComment.add( line );
133            }
134            else if ( line.startsWith( MESSAGE_TOKEN ) )
135            {
136                spoolingComments = true;
137            }
138            else if ( line.startsWith( REVNO_TAG ) )
139            {
140                tmpLine = line.substring( REVNO_TAG.length() );
141                tmpLine = tmpLine.trim();
142                currentRevision = tmpLine.substring( tmpLine.indexOf( ':' ) + 1 );
143                currentChange.setRevision( currentRevision );
144    
145            }
146            else if ( line.startsWith( TAG_TAG ) )
147            {
148                tmpLine = line.substring( TAG_TAG.length() ).trim();
149                currentTag = tmpLine;
150            }
151            else if ( line.startsWith( AUTHOR_TAG ) )
152            {
153                tmpLine = line.substring( AUTHOR_TAG.length() );
154                tmpLine = tmpLine.trim();
155                currentChange.setAuthor( tmpLine );
156            }
157            else if ( line.startsWith( TIME_STAMP_TOKEN ) )
158            {
159                // TODO: FIX Date Parsing to match Mercurial or fix with template
160                tmpLine = line.substring( TIME_STAMP_TOKEN.length() ).trim();
161                Date date = parseDate( tmpLine, userDatePattern, TIME_PATTERN, Locale.ENGLISH );
162                currentChange.setDate( date );
163            }
164            else if ( line.startsWith( FILES_TOKEN ) )
165            {
166                tmpLine = line.substring( FILES_TOKEN.length() ).trim();
167                String[] files = tmpLine.split( " " );
168                for ( int i = 0; i < files.length; i++ )
169                {
170                    String file = files[i];
171                    ChangeFile changeFile = new ChangeFile( file, currentRevision );
172                    currentChange.addFile( changeFile );
173                }
174            }
175            else if ( line.length() > 0 )
176            {
177                if ( getLogger().isWarnEnabled() )
178                {
179                    getLogger().warn( "Could not figure out: " + line );
180                }
181            }
182    
183            // record previous line
184            prevLine = line;
185            prevPrevLine = prevLine;
186        }
187    }