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(final byte[] b, final int offset) {
73 super(b, offset);
74 }
75
76 @Override
77 @SuppressWarnings("unchecked")
78 public List<? extends CombinedHunkHeader> getHunks() {
79 return (List<CombinedHunkHeader>) super.getHunks();
80 }
81
82
83 @Override
84 public int getParentCount() {
85 return oldIds.length;
86 }
87
88
89 @Override
90 public FileMode getOldMode() {
91 return getOldMode(0);
92 }
93
94
95
96
97
98
99
100
101 public FileMode getOldMode(final int nthParent) {
102 return oldModes[nthParent];
103 }
104
105
106 @Override
107 public AbbreviatedObjectId getOldId() {
108 return getOldId(0);
109 }
110
111
112
113
114
115
116
117
118 public AbbreviatedObjectId getOldId(final int nthParent) {
119 return oldIds[nthParent];
120 }
121
122 @Override
123 public String getScriptText(final Charset ocs, final Charset ncs) {
124 final Charset[] cs = new Charset[getParentCount() + 1];
125 Arrays.fill(cs, ocs);
126 cs[getParentCount()] = ncs;
127 return getScriptText(cs);
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141 @Override
142 public String getScriptText(final Charset[] charsetGuess) {
143 return super.getScriptText(charsetGuess);
144 }
145
146 @Override
147 int parseGitHeaders(int ptr, final int end) {
148 while (ptr < end) {
149 final int eol = nextLF(buf, ptr);
150 if (isHunkHdr(buf, ptr, end) >= 1) {
151
152 break;
153
154 } else if (match(buf, ptr, OLD_NAME) >= 0) {
155 parseOldName(ptr, eol);
156
157 } else if (match(buf, ptr, NEW_NAME) >= 0) {
158 parseNewName(ptr, eol);
159
160 } else if (match(buf, ptr, INDEX) >= 0) {
161 parseIndexLine(ptr + INDEX.length, eol);
162
163 } else if (match(buf, ptr, MODE) >= 0) {
164 parseModeLine(ptr + MODE.length, eol);
165
166 } else if (match(buf, ptr, NEW_FILE_MODE) >= 0) {
167 parseNewFileMode(ptr, eol);
168
169 } else if (match(buf, ptr, DELETED_FILE_MODE) >= 0) {
170 parseDeletedFileMode(ptr + DELETED_FILE_MODE.length, eol);
171
172 } else {
173
174 break;
175 }
176
177 ptr = eol;
178 }
179 return ptr;
180 }
181
182 @Override
183 protected void parseIndexLine(int ptr, final int eol) {
184
185
186 final List<AbbreviatedObjectId> ids = new ArrayList<>();
187 while (ptr < eol) {
188 final int comma = nextLF(buf, ptr, ',');
189 if (eol <= comma)
190 break;
191 ids.add(AbbreviatedObjectId.fromString(buf, ptr, comma - 1));
192 ptr = comma;
193 }
194
195 oldIds = new AbbreviatedObjectId[ids.size() + 1];
196 ids.toArray(oldIds);
197 final int dot2 = nextLF(buf, ptr, '.');
198 oldIds[ids.size()] = AbbreviatedObjectId.fromString(buf, ptr, dot2 - 1);
199 newId = AbbreviatedObjectId.fromString(buf, dot2 + 1, eol - 1);
200 oldModes = new FileMode[oldIds.length];
201 }
202
203 @Override
204 protected void parseNewFileMode(final int ptr, final int eol) {
205 for (int i = 0; i < oldModes.length; i++)
206 oldModes[i] = FileMode.MISSING;
207 super.parseNewFileMode(ptr, eol);
208 }
209
210 @Override
211 HunkHeader newHunkHeader(final int offset) {
212 return new CombinedHunkHeader(this, offset);
213 }
214
215 private void parseModeLine(int ptr, final int eol) {
216
217
218 int n = 0;
219 while (ptr < eol) {
220 final int comma = nextLF(buf, ptr, ',');
221 if (eol <= comma)
222 break;
223 oldModes[n++] = parseFileMode(ptr, comma);
224 ptr = comma;
225 }
226 final int dot2 = nextLF(buf, ptr, '.');
227 oldModes[n] = parseFileMode(ptr, dot2);
228 newMode = parseFileMode(dot2 + 1, eol);
229 }
230
231 private void parseDeletedFileMode(int ptr, final int eol) {
232
233
234 changeType = ChangeType.DELETE;
235 int n = 0;
236 while (ptr < eol) {
237 final int comma = nextLF(buf, ptr, ',');
238 if (eol <= comma)
239 break;
240 oldModes[n++] = parseFileMode(ptr, comma);
241 ptr = comma;
242 }
243 oldModes[n] = parseFileMode(ptr, eol);
244 newMode = FileMode.MISSING;
245 }
246 }