1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.patch;
45
46 import static org.eclipse.jgit.lib.Constants.encodeASCII;
47 import static org.eclipse.jgit.util.RawParseUtils.match;
48 import static org.eclipse.jgit.util.RawParseUtils.nextLF;
49
50 import java.nio.charset.Charset;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.List;
54
55 import org.eclipse.jgit.lib.AbbreviatedObjectId;
56 import org.eclipse.jgit.lib.FileMode;
57
58
59
60
61
62
63
64
65 public class CombinedFileHeader extends FileHeader {
66 private static final byte[] MODE = encodeASCII("mode ");
67
68 private AbbreviatedObjectId[] oldIds;
69
70 private FileMode[] oldModes;
71
72 CombinedFileHeader(byte[] b, int offset) {
73 super(b, offset);
74 }
75
76
77 @Override
78 @SuppressWarnings("unchecked")
79 public List<? extends CombinedHunkHeader> getHunks() {
80 return (List<CombinedHunkHeader>) super.getHunks();
81 }
82
83
84
85
86
87
88
89 @Override
90 public int getParentCount() {
91 return oldIds.length;
92 }
93
94
95
96
97
98
99 @Override
100 public FileMode getOldMode() {
101 return getOldMode(0);
102 }
103
104
105
106
107
108
109
110
111 public FileMode getOldMode(int nthParent) {
112 return oldModes[nthParent];
113 }
114
115
116
117
118
119
120
121 @Override
122 public AbbreviatedObjectId getOldId() {
123 return getOldId(0);
124 }
125
126
127
128
129
130
131
132
133 public AbbreviatedObjectId getOldId(int nthParent) {
134 return oldIds[nthParent];
135 }
136
137
138 @Override
139 public String getScriptText(Charset ocs, Charset ncs) {
140 final Charset[] cs = new Charset[getParentCount() + 1];
141 Arrays.fill(cs, ocs);
142 cs[getParentCount()] = ncs;
143 return getScriptText(cs);
144 }
145
146
147
148
149
150
151 @Override
152 public String getScriptText(Charset[] charsetGuess) {
153 return super.getScriptText(charsetGuess);
154 }
155
156 @Override
157 int parseGitHeaders(int ptr, int end) {
158 while (ptr < end) {
159 final int eol = nextLF(buf, ptr);
160 if (isHunkHdr(buf, ptr, end) >= 1) {
161
162 break;
163
164 } else if (match(buf, ptr, OLD_NAME) >= 0) {
165 parseOldName(ptr, eol);
166
167 } else if (match(buf, ptr, NEW_NAME) >= 0) {
168 parseNewName(ptr, eol);
169
170 } else if (match(buf, ptr, INDEX) >= 0) {
171 parseIndexLine(ptr + INDEX.length, eol);
172
173 } else if (match(buf, ptr, MODE) >= 0) {
174 parseModeLine(ptr + MODE.length, eol);
175
176 } else if (match(buf, ptr, NEW_FILE_MODE) >= 0) {
177 parseNewFileMode(ptr, eol);
178
179 } else if (match(buf, ptr, DELETED_FILE_MODE) >= 0) {
180 parseDeletedFileMode(ptr + DELETED_FILE_MODE.length, eol);
181
182 } else {
183
184 break;
185 }
186
187 ptr = eol;
188 }
189 return ptr;
190 }
191
192
193 @Override
194 protected void parseIndexLine(int ptr, int eol) {
195
196
197 final List<AbbreviatedObjectId> ids = new ArrayList<>();
198 while (ptr < eol) {
199 final int comma = nextLF(buf, ptr, ',');
200 if (eol <= comma)
201 break;
202 ids.add(AbbreviatedObjectId.fromString(buf, ptr, comma - 1));
203 ptr = comma;
204 }
205
206 oldIds = new AbbreviatedObjectId[ids.size() + 1];
207 ids.toArray(oldIds);
208 final int dot2 = nextLF(buf, ptr, '.');
209 oldIds[ids.size()] = AbbreviatedObjectId.fromString(buf, ptr, dot2 - 1);
210 newId = AbbreviatedObjectId.fromString(buf, dot2 + 1, eol - 1);
211 oldModes = new FileMode[oldIds.length];
212 }
213
214
215 @Override
216 protected void parseNewFileMode(int ptr, int eol) {
217 for (int i = 0; i < oldModes.length; i++)
218 oldModes[i] = FileMode.MISSING;
219 super.parseNewFileMode(ptr, eol);
220 }
221
222 @Override
223 HunkHeader newHunkHeader(int offset) {
224 return new CombinedHunkHeader(this, offset);
225 }
226
227 private void parseModeLine(int ptr, int eol) {
228
229
230 int n = 0;
231 while (ptr < eol) {
232 final int comma = nextLF(buf, ptr, ',');
233 if (eol <= comma)
234 break;
235 oldModes[n++] = parseFileMode(ptr, comma);
236 ptr = comma;
237 }
238 final int dot2 = nextLF(buf, ptr, '.');
239 oldModes[n] = parseFileMode(ptr, dot2);
240 newMode = parseFileMode(dot2 + 1, eol);
241 }
242
243 private void parseDeletedFileMode(int ptr, int eol) {
244
245
246 changeType = ChangeType.DELETE;
247 int n = 0;
248 while (ptr < eol) {
249 final int comma = nextLF(buf, ptr, ',');
250 if (eol <= comma)
251 break;
252 oldModes[n++] = parseFileMode(ptr, comma);
253 ptr = comma;
254 }
255 oldModes[n] = parseFileMode(ptr, eol);
256 newMode = FileMode.MISSING;
257 }
258 }