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