001    package org.apache.maven.scm.provider.hg.command.diff;
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.ScmFile;
023    import org.apache.maven.scm.ScmFileStatus;
024    import org.apache.maven.scm.log.ScmLogger;
025    import org.apache.maven.scm.provider.hg.command.HgConsumer;
026    
027    import java.io.File;
028    import java.util.ArrayList;
029    import java.util.HashMap;
030    import java.util.List;
031    import java.util.Map;
032    
033    /**
034     * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
035     * @author Olivier Lamy
036     * @version $Id: HgDiffConsumer.java 1306867 2012-03-29 13:45:10Z olamy $
037     */
038    public class HgDiffConsumer
039        extends HgConsumer
040    {
041    
042        // private static final String MODIFIED_FILE_TOKEN = "=== modified file ";
043    
044        private static final String INDEX_TOKEN = "diff -r ";
045    
046        private static final String FILE_SEPARATOR_TOKEN = "===";
047    
048        private static final String START_REVISION_TOKEN = "---";
049    
050        private static final String END_REVISION_TOKEN = "+++";
051    
052        private static final String ADDED_LINE_TOKEN = "+";
053    
054        private static final String REMOVED_LINE_TOKEN = "-";
055    
056        private static final String UNCHANGED_LINE_TOKEN = " ";
057    
058        private static final String CHANGE_SEPARATOR_TOKEN = "@@";
059    
060        private static final String NO_NEWLINE_TOKEN = "\\ No newline at end of file";
061    
062        private static final int HASH_ID_LEN = 12;
063    
064        private ScmLogger logger;
065    
066        private String currentFile;
067    
068        private StringBuilder currentDifference;
069    
070        private List<ScmFile> changedFiles = new ArrayList<ScmFile>();
071    
072        private Map<String,CharSequence> differences = new HashMap<String,CharSequence>();
073    
074        private StringBuilder patch = new StringBuilder();
075    
076        @SuppressWarnings( "unused" )
077        private File workingDirectory;
078    
079    
080        public HgDiffConsumer( ScmLogger logger, File workingDirectory )
081        {
082            super( logger );
083            this.logger = logger;
084            this.workingDirectory = workingDirectory;
085        }
086    
087        // ----------------------------------------------------------------------
088        // StreamConsumer Implementation
089        // ----------------------------------------------------------------------
090    
091        /** {@inheritDoc} */
092        public void consumeLine( String line )
093        {
094            if ( line.startsWith( INDEX_TOKEN ) )
095            {
096                // start a new file
097                currentFile = line.substring( INDEX_TOKEN.length() + HASH_ID_LEN + 1 );
098    
099                changedFiles.add( new ScmFile( currentFile, ScmFileStatus.MODIFIED ) );
100    
101                currentDifference = new StringBuilder();
102    
103                differences.put( currentFile, currentDifference );
104    
105                patch.append( line ).append( "\n" );
106    
107                return;
108            }
109    
110            if ( currentFile == null )
111            {
112                if ( logger.isWarnEnabled() )
113                {
114                    logger.warn( "Unparseable line: '" + line + "'" );
115                }
116                patch.append( line ).append( "\n" );
117                return;
118            }
119    
120            if ( line.startsWith( FILE_SEPARATOR_TOKEN ) )
121            {
122                // skip
123                patch.append( line ).append( "\n" );
124            }
125            else if ( line.startsWith( START_REVISION_TOKEN ) )
126            {
127                // skip, though could parse to verify filename, start revision
128                patch.append( line ).append( "\n" );
129            }
130            else if ( line.startsWith( END_REVISION_TOKEN ) )
131            {
132                // skip, though could parse to verify filename, end revision
133                patch.append( line ).append( "\n" );
134            }
135            else if ( line.startsWith( ADDED_LINE_TOKEN ) || line.startsWith( REMOVED_LINE_TOKEN )
136                || line.startsWith( UNCHANGED_LINE_TOKEN ) || line.startsWith( CHANGE_SEPARATOR_TOKEN )
137                || line.equals( NO_NEWLINE_TOKEN ) )
138            {
139                // add to buffer
140                currentDifference.append( line ).append( "\n" );
141                patch.append( line ).append( "\n" );
142            }
143            else
144            {
145                // TODO: handle property differences
146    
147                if ( logger.isWarnEnabled() )
148                {
149                    logger.warn( "Unparseable line: '" + line + "'" );
150                }
151                patch.append( line ).append( "\n" );
152                // skip to next file
153                currentFile = null;
154                currentDifference = null;
155            }
156        }
157    
158        public List<ScmFile> getChangedFiles()
159        {
160            return changedFiles;
161        }
162    
163        public Map<String,CharSequence> getDifferences()
164        {
165            return differences;
166        }
167    
168        public String getPatch()
169        {
170            return patch.toString();
171        }
172    }