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