001 package org.apache.maven.scm.provider.git.gitexe.command.status;
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.commons.lang.StringUtils;
023 import org.apache.maven.scm.ScmFile;
024 import org.apache.maven.scm.ScmFileStatus;
025 import org.apache.maven.scm.log.ScmLogger;
026 import org.apache.regexp.RE;
027 import org.apache.regexp.RESyntaxException;
028 import org.codehaus.plexus.util.cli.StreamConsumer;
029
030 import java.io.File;
031 import java.util.ArrayList;
032 import java.util.List;
033
034 /**
035 * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
036 */
037 public class GitStatusConsumer
038 implements StreamConsumer
039 {
040 /**
041 * The pattern used to match added file lines
042 */
043 private static final String ADDED_PATTERN = "^A[ M]* (.*)$";
044
045 /**
046 * The pattern used to match modified file lines
047 */
048 private static final String MODIFIED_PATTERN = "^ *M[ M]* (.*)$";
049
050 /**
051 * The pattern used to match deleted file lines
052 */
053 private static final String DELETED_PATTERN = "^ *D * (.*)$";
054
055 /**
056 * The pattern used to match renamed file lines
057 */
058 private static final String RENAMED_PATTERN = "R (.*) -> (.*)$";
059
060 /**
061 * @see #ADDED_PATTERN
062 */
063 private RE addedRegexp;
064
065 /**
066 * @see #MODIFIED_PATTERN
067 */
068 private RE modifiedRegexp;
069
070 /**
071 * @see #DELETED_PATTERN
072 */
073 private RE deletedRegexp;
074
075 /**
076 * @see #RENAMED_PATTERN
077 */
078 private RE renamedRegexp;
079
080 private ScmLogger logger;
081
082 private File workingDirectory;
083
084 private List<ScmFile> changedFiles = new ArrayList<ScmFile>();
085
086 // ----------------------------------------------------------------------
087 //
088 // ----------------------------------------------------------------------
089
090 public GitStatusConsumer( ScmLogger logger, File workingDirectory )
091 {
092 this.logger = logger;
093 this.workingDirectory = workingDirectory;
094
095 try
096 {
097 addedRegexp = new RE( ADDED_PATTERN );
098 modifiedRegexp = new RE( MODIFIED_PATTERN );
099 deletedRegexp = new RE( DELETED_PATTERN );
100 renamedRegexp = new RE( RENAMED_PATTERN );
101 }
102 catch ( RESyntaxException ex )
103 {
104 throw new RuntimeException(
105 "INTERNAL ERROR: Could not create regexp to parse git log file. This shouldn't happen. Something is probably wrong with the oro installation.",
106 ex );
107 }
108 }
109
110 // ----------------------------------------------------------------------
111 // StreamConsumer Implementation
112 // ----------------------------------------------------------------------
113
114 /**
115 * {@inheritDoc}
116 */
117 public void consumeLine( String line )
118 {
119 if ( logger.isDebugEnabled() )
120 {
121 logger.debug( line );
122 }
123 if ( StringUtils.isEmpty( line ) )
124 {
125 return;
126 }
127
128 ScmFileStatus status = null;
129
130 List<String> files = new ArrayList<String>();
131
132 if ( addedRegexp.match( line ) )
133 {
134 status = ScmFileStatus.ADDED;
135 files.add( addedRegexp.getParen( 1 ) );
136 }
137 else if ( modifiedRegexp.match( line ) )
138 {
139 status = ScmFileStatus.MODIFIED;
140 files.add( modifiedRegexp.getParen( 1 ) );
141 }
142 else if ( deletedRegexp.match( line ) )
143 {
144 status = ScmFileStatus.DELETED;
145 files.add( deletedRegexp.getParen( 1 ) );
146 }
147 else if ( renamedRegexp.match( line ) )
148 {
149 status = ScmFileStatus.RENAMED;
150 files.add( StringUtils.trim( renamedRegexp.getParen( 1 ) ) );
151 files.add( StringUtils.trim( renamedRegexp.getParen( 2 ) ) );
152 logger.debug( "RENAMED status for line '" + line + "' files added '" + renamedRegexp.getParen( 1 ) + "' '"
153 + renamedRegexp.getParen( 2 ) );
154 }
155
156 // If the file isn't a file; don't add it.
157 if ( !files.isEmpty() && status != null )
158 {
159 if ( workingDirectory != null )
160 {
161 if ( status == ScmFileStatus.RENAMED )
162 {
163 String oldFilePath = files.get( 0 );
164 String newFilePath = files.get( 1 );
165 if ( new File( workingDirectory, oldFilePath ).isFile() )
166 {
167 logger.debug(
168 "file '" + new File( workingDirectory, oldFilePath ).getAbsolutePath() + "' is a file" );
169 return;
170 }
171 else
172 {
173 logger.debug(
174 "file '" + new File( workingDirectory, oldFilePath ).getAbsolutePath() + "' not a file" );
175 }
176 if ( !new File( workingDirectory, newFilePath ).isFile() )
177 {
178 logger.debug(
179 "file '" + new File( workingDirectory, newFilePath ).getAbsolutePath() + "' not a file" );
180 return;
181 }
182 else
183 {
184 logger.debug(
185 "file '" + new File( workingDirectory, newFilePath ).getAbsolutePath() + "' is a file" );
186 }
187 }
188 else if ( status == ScmFileStatus.DELETED )
189 {
190 if ( new File( workingDirectory, files.get( 0 ) ).isFile() )
191 {
192 return;
193 }
194 }
195 else
196 {
197 if ( !new File( workingDirectory, files.get( 0 ) ).isFile() )
198 {
199 return;
200 }
201 }
202 }
203
204 for ( String file : files )
205 {
206 changedFiles.add( new ScmFile( file, status ) );
207 }
208 }
209 }
210
211 public List<ScmFile> getChangedFiles()
212 {
213 return changedFiles;
214 }
215 }