1 package org.apache.maven.scm.provider.git.command.diff;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.scm.ScmFile;
23 import org.apache.maven.scm.ScmFileStatus;
24 import org.apache.maven.scm.log.ScmLogger;
25 import org.codehaus.plexus.util.cli.StreamConsumer;
26
27 import java.io.File;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34
35
36
37
38
39
40
41 public class GitDiffConsumer
42 implements StreamConsumer
43 {
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 private static final Pattern DIFF_FILES_PATTERN = Pattern.compile( "^diff --git\\sa/(.*)\\sb/(.*)" );
60
61 private static final String START_REVISION_TOKEN = "---";
62
63 private static final String END_REVISION_TOKEN = "+++";
64
65 private static final String ADDED_LINE_TOKEN = "+";
66
67 private static final String REMOVED_LINE_TOKEN = "-";
68
69 private static final String UNCHANGED_LINE_TOKEN = " ";
70
71 private static final String CHANGE_SEPARATOR_TOKEN = "@@";
72
73 private static final String NO_NEWLINE_TOKEN = "\\ No newline at end of file";
74
75 private static final String INDEX_LINE_TOKEN = "index ";
76
77 private static final String NEW_FILE_MODE_TOKEN = "new file mode ";
78
79 private static final String DELETED_FILE_MODE_TOKEN = "deleted file mode ";
80
81 private ScmLogger logger;
82
83 private String currentFile;
84
85 private StringBuilder currentDifference;
86
87 private List<ScmFile> changedFiles = new ArrayList<ScmFile>();
88
89 private Map<String, CharSequence> differences = new HashMap<String, CharSequence>();
90
91 private StringBuilder patch = new StringBuilder();
92
93
94
95
96
97 public GitDiffConsumer( ScmLogger logger, File workingDirectory )
98 {
99 this.logger = logger;
100 }
101
102
103
104
105
106
107 public void consumeLine( String line )
108 {
109 Matcher matcher = DIFF_FILES_PATTERN.matcher( line );
110 if ( matcher.matches() )
111 {
112
113 currentFile = matcher.group( 1 );
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 else if ( line.startsWith( INDEX_LINE_TOKEN ) )
136 {
137
138 patch.append( line ).append( "\n" );
139 }
140 else if ( line.startsWith( NEW_FILE_MODE_TOKEN ) || line.startsWith( DELETED_FILE_MODE_TOKEN ) )
141 {
142
143 patch.append( line ).append( "\n" );
144 }
145 else if ( line.startsWith( START_REVISION_TOKEN ) )
146 {
147
148 patch.append( line ).append( "\n" );
149 }
150 else if ( line.startsWith( END_REVISION_TOKEN ) )
151 {
152
153 patch.append( line ).append( "\n" );
154 }
155 else if ( line.startsWith( ADDED_LINE_TOKEN ) || line.startsWith( REMOVED_LINE_TOKEN )
156 || line.startsWith( UNCHANGED_LINE_TOKEN ) || line.startsWith( CHANGE_SEPARATOR_TOKEN )
157 || line.equals( NO_NEWLINE_TOKEN ) )
158 {
159
160 currentDifference.append( line ).append( "\n" );
161 patch.append( line ).append( "\n" );
162 }
163 else
164 {
165
166
167 if ( logger.isWarnEnabled() )
168 {
169 logger.warn( "Unparseable line: '" + line + "'" );
170 }
171 patch.append( line ).append( "\n" );
172
173 currentFile = null;
174 currentDifference = null;
175 }
176 }
177
178 public List<ScmFile> getChangedFiles()
179 {
180 return changedFiles;
181 }
182
183 public Map<String, CharSequence> getDifferences()
184 {
185 return differences;
186 }
187
188 public String getPatch()
189 {
190 return patch.toString();
191 }
192
193 }