001package org.apache.maven.scm.provider.cvslib.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 022import org.apache.maven.scm.ScmFile; 023import org.apache.maven.scm.ScmFileStatus; 024import org.apache.maven.scm.log.ScmLogger; 025import org.codehaus.plexus.util.cli.StreamConsumer; 026 027import java.io.File; 028import java.util.ArrayList; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033/** 034 * @author <a href="mailto:brett@apache.org">Brett Porter</a> 035 * @author Olivier Lamy 036 * 037 * @todo share with SVN (3 extra lines can be ignored) 038 */ 039public class CvsDiffConsumer 040 implements StreamConsumer 041{ 042 // 043 // Index: plugin.jelly 044 // =================================================================== 045 // RCS file: /home/cvs/maven-scm/maven-scm-providers/maven-scm-provider-cvs/ 046 // src/main/resources/META-INF/plexus/components.xml,v 047 // retrieving revision 1.2 048 // diff -u -r1.2 components.xml 049 // --- plugin.jelly (revision 124799) 050 // +++ plugin.jelly (working copy) 051 // 052 053 private static final String RCS_TOKEN = "RCS file: "; 054 055 private static final String RETRIEVING_TOKEN = "retrieving revision "; 056 057 private static final String DIFF_TOKEN = "diff "; 058 059 private static final String INDEX_TOKEN = "Index: "; 060 061 private static final String FILE_SEPARATOR_TOKEN = "==="; 062 063 private static final String START_REVISION_TOKEN = "---"; 064 065 private static final String END_REVISION_TOKEN = "+++"; 066 067 private static final String ADDED_LINE_TOKEN = "+"; 068 069 private static final String REMOVED_LINE_TOKEN = "-"; 070 071 private static final String UNCHANGED_LINE_TOKEN = " "; 072 073 private static final String CHANGE_SEPARATOR_TOKEN = "@@"; 074 075 private static final String NO_NEWLINE_TOKEN = "\\ No newline at end of file"; 076 077 private ScmLogger logger; 078 079 private String currentFile; 080 081 private StringBuilder currentDifference; 082 083 private List<ScmFile> changedFiles = new ArrayList<ScmFile>(); 084 085 private Map<String, CharSequence> differences = new HashMap<String, CharSequence>(); 086 087 private StringBuilder patch = new StringBuilder(); 088 089 // ---------------------------------------------------------------------- 090 // 091 // ---------------------------------------------------------------------- 092 093 public CvsDiffConsumer( ScmLogger logger, File workingDirectory ) 094 { 095 this.logger = logger; 096 } 097 098 // ---------------------------------------------------------------------- 099 // StreamConsumer Implementation 100 // ---------------------------------------------------------------------- 101 102 /** {@inheritDoc} */ 103 public void consumeLine( String line ) 104 { 105 if ( logger.isDebugEnabled() ) 106 { 107 logger.debug( line ); 108 } 109 110 if ( line.startsWith( INDEX_TOKEN ) ) 111 { 112 // start a new file 113 currentFile = line.substring( INDEX_TOKEN.length() ); 114 115 changedFiles.add( new ScmFile( currentFile, ScmFileStatus.MODIFIED ) ); 116 117 currentDifference = new StringBuilder(); 118 119 differences.put( currentFile, currentDifference ); 120 121 patch.append( line ).append( "\n" ); 122 123 return; 124 } 125 126 if ( currentFile == null ) 127 { 128 if ( logger.isWarnEnabled() ) 129 { 130 logger.warn( "Unparseable line: '" + line + "'" ); 131 } 132 patch.append( line ).append( "\n" ); 133 return; 134 } 135 136 if ( line.startsWith( FILE_SEPARATOR_TOKEN ) ) 137 { 138 // skip 139 patch.append( line ).append( "\n" ); 140 } 141 else if ( line.startsWith( START_REVISION_TOKEN ) ) 142 { 143 // skip, though could parse to verify filename, start revision 144 patch.append( line ).append( "\n" ); 145 } 146 else if ( line.startsWith( END_REVISION_TOKEN ) ) 147 { 148 // skip, though could parse to verify filename, end revision 149 patch.append( line ).append( "\n" ); 150 } 151 else if ( line.startsWith( RCS_TOKEN ) ) 152 { 153 // skip, though could parse to verify filename 154 } 155 else if ( line.startsWith( RETRIEVING_TOKEN ) ) 156 { 157 // skip, though could parse to verify version 158 } 159 else if ( line.startsWith( DIFF_TOKEN ) ) 160 { 161 // skip, though could parse to verify command 162 } 163 else if ( line.startsWith( ADDED_LINE_TOKEN ) || line.startsWith( REMOVED_LINE_TOKEN ) 164 || line.startsWith( UNCHANGED_LINE_TOKEN ) || line.startsWith( CHANGE_SEPARATOR_TOKEN ) 165 || line.equals( NO_NEWLINE_TOKEN ) ) 166 { 167 // add to buffer 168 currentDifference.append( line ).append( "\n" ); 169 patch.append( line ).append( "\n" ); 170 } 171 else 172 { 173 if ( logger.isWarnEnabled() ) 174 { 175 logger.warn( "Unparseable line: '" + line + "'" ); 176 } 177 patch.append( line ).append( "\n" ); 178 // skip to next file 179 currentFile = null; 180 currentDifference = null; 181 } 182 } 183 184 public List<ScmFile> getChangedFiles() 185 { 186 return changedFiles; 187 } 188 189 public Map<String, CharSequence> getDifferences() 190 { 191 return differences; 192 } 193 194 public String getPatch() 195 { 196 return patch.toString(); 197 } 198 199}