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 public class GitDiffConsumer extends AbstractConsumer {
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 private static final Pattern DIFF_FILES_PATTERN = Pattern.compile("^diff --git\\sa/(.*)\\sb/(.*)");
54
55 private static final String START_REVISION_TOKEN = "---";
56
57 private static final String END_REVISION_TOKEN = "+++";
58
59 private static final String ADDED_LINE_TOKEN = "+";
60
61 private static final String REMOVED_LINE_TOKEN = "-";
62
63 private static final String UNCHANGED_LINE_TOKEN = " ";
64
65 private static final String CHANGE_SEPARATOR_TOKEN = "@@";
66
67 private static final String NO_NEWLINE_TOKEN = "\\ No newline at end of file";
68
69 private static final String INDEX_LINE_TOKEN = "index ";
70
71 private static final String SIMILARITY_INDEX_LINE_TOKEN = "similarity index ";
72
73 private static final String RENAME_FROM_LINE_TOKEN = "rename from ";
74
75 private static final String RENAME_TO_LINE_TOKEN = "rename to ";
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 String currentFile;
82
83 private StringBuilder currentDifference;
84
85 private final List<ScmFile> changedFiles = new ArrayList<>();
86
87 private final Map<String, CharSequence> differences = new HashMap<>();
88
89 private final StringBuilder patch = new StringBuilder();
90
91
92
93
94
95 public GitDiffConsumer(File workingDirectory) {
96
97 }
98
99
100
101
102
103
104
105
106 public void consumeLine(String line) {
107 Matcher matcher = DIFF_FILES_PATTERN.matcher(line);
108 if (matcher.matches()) {
109
110 currentFile = matcher.group(1);
111
112 changedFiles.add(new ScmFile(currentFile, ScmFileStatus.MODIFIED));
113
114 currentDifference = new StringBuilder();
115
116 differences.put(currentFile, currentDifference);
117
118 patch.append(line).append("\n");
119
120 return;
121 }
122
123 if (currentFile == null) {
124 if (logger.isWarnEnabled()) {
125 logger.warn("Unparseable line: '" + line + "'");
126 }
127 patch.append(line).append("\n");
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 }