1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.lib;
12
13 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
14 import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
15 import static org.eclipse.jgit.lib.Constants.encode;
16 import static org.eclipse.jgit.lib.FileMode.GITLINK;
17 import static org.eclipse.jgit.lib.FileMode.REGULAR_FILE;
18 import static org.eclipse.jgit.lib.FileMode.TREE;
19
20 import java.io.IOException;
21
22 import org.eclipse.jgit.errors.CorruptObjectException;
23 import org.eclipse.jgit.internal.JGitText;
24 import org.eclipse.jgit.revwalk.RevBlob;
25 import org.eclipse.jgit.revwalk.RevCommit;
26 import org.eclipse.jgit.revwalk.RevTree;
27 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
28 import org.eclipse.jgit.util.TemporaryBuffer;
29
30
31
32
33
34
35
36
37
38
39
40 public class TreeFormatter {
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public static int entrySize(FileMode mode, int nameLen) {
55 return mode.copyToLength() + nameLen + OBJECT_ID_LENGTH + 2;
56 }
57
58 private byte[] buf;
59
60 private int ptr;
61
62 private TemporaryBuffer.Heap overflowBuffer;
63
64
65
66
67 public TreeFormatter() {
68 this(8192);
69 }
70
71
72
73
74
75
76
77
78
79 public TreeFormatter(int size) {
80 buf = new byte[size];
81 }
82
83
84
85
86
87
88
89
90
91 public void append(String name, RevCommit commit) {
92 append(name, GITLINK, commit);
93 }
94
95
96
97
98
99
100
101
102
103 public void append(String name, RevTree tree) {
104 append(name, TREE, tree);
105 }
106
107
108
109
110
111
112
113
114
115 public void append(String name, RevBlob blob) {
116 append(name, REGULAR_FILE, blob);
117 }
118
119
120
121
122
123
124
125
126
127
128
129 public void append(String name, FileMode mode, AnyObjectId id) {
130 append(encode(name), mode, id);
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144 public void append(byte[] name, FileMode mode, AnyObjectId id) {
145 append(name, 0, name.length, mode, id);
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public void append(byte[] nameBuf, int namePos, int nameLen, FileMode mode,
165 AnyObjectId id) {
166 append(nameBuf, namePos, nameLen, mode, id, false);
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 public void append(byte[] nameBuf, int namePos, int nameLen, FileMode mode,
189 AnyObjectId id, boolean allowEmptyName) {
190 if (nameLen == 0 && !allowEmptyName) {
191 throw new IllegalArgumentException(
192 JGitText.get().invalidTreeZeroLengthName);
193 }
194 if (fmtBuf(nameBuf, namePos, nameLen, mode)) {
195 id.copyRawTo(buf, ptr);
196 ptr += OBJECT_ID_LENGTH;
197
198 } else {
199 try {
200 fmtOverflowBuffer(nameBuf, namePos, nameLen, mode);
201 id.copyRawTo(overflowBuffer);
202 } catch (IOException badBuffer) {
203
204 throw new RuntimeException(badBuffer);
205 }
206 }
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 public void append(byte[] nameBuf, int namePos, int nameLen, FileMode mode,
228 byte[] idBuf, int idPos) {
229 if (fmtBuf(nameBuf, namePos, nameLen, mode)) {
230 System.arraycopy(idBuf, idPos, buf, ptr, OBJECT_ID_LENGTH);
231 ptr += OBJECT_ID_LENGTH;
232
233 } else {
234 try {
235 fmtOverflowBuffer(nameBuf, namePos, nameLen, mode);
236 overflowBuffer.write(idBuf, idPos, OBJECT_ID_LENGTH);
237 } catch (IOException badBuffer) {
238
239 throw new RuntimeException(badBuffer);
240 }
241 }
242 }
243
244 private boolean fmtBuf(byte[] nameBuf, int namePos, int nameLen,
245 FileMode mode) {
246 if (buf == null || buf.length < ptr + entrySize(mode, nameLen))
247 return false;
248
249 mode.copyTo(buf, ptr);
250 ptr += mode.copyToLength();
251 buf[ptr++] = ' ';
252
253 System.arraycopy(nameBuf, namePos, buf, ptr, nameLen);
254 ptr += nameLen;
255 buf[ptr++] = 0;
256 return true;
257 }
258
259 private void fmtOverflowBuffer(byte[] nameBuf, int namePos, int nameLen,
260 FileMode mode) throws IOException {
261 if (buf != null) {
262 overflowBuffer = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
263 overflowBuffer.write(buf, 0, ptr);
264 buf = null;
265 }
266
267 mode.copyTo(overflowBuffer);
268 overflowBuffer.write((byte) ' ');
269 overflowBuffer.write(nameBuf, namePos, nameLen);
270 overflowBuffer.write((byte) 0);
271 }
272
273
274
275
276
277
278
279
280
281
282 public ObjectId insertTo(ObjectInserter ins) throws IOException {
283 if (buf != null)
284 return ins.insert(OBJ_TREE, buf, 0, ptr);
285
286 final long len = overflowBuffer.length();
287 return ins.insert(OBJ_TREE, len, overflowBuffer.openInputStream());
288 }
289
290
291
292
293
294
295
296 public ObjectId computeId(ObjectInserter ins) {
297 if (buf != null)
298 return ins.idFor(OBJ_TREE, buf, 0, ptr);
299
300 final long len = overflowBuffer.length();
301 try {
302 return ins.idFor(OBJ_TREE, len, overflowBuffer.openInputStream());
303 } catch (IOException e) {
304
305 throw new RuntimeException(e);
306 }
307 }
308
309
310
311
312
313
314
315
316
317
318
319
320 public byte[] toByteArray() {
321 if (buf != null) {
322 byte[] r = new byte[ptr];
323 System.arraycopy(buf, 0, r, 0, ptr);
324 return r;
325 }
326
327 try {
328 return overflowBuffer.toByteArray();
329 } catch (IOException err) {
330
331 throw new RuntimeException(err);
332 }
333 }
334
335
336 @SuppressWarnings("nls")
337 @Override
338 public String toString() {
339 byte[] raw = toByteArray();
340
341 CanonicalTreeParser p = new CanonicalTreeParser();
342 p.reset(raw);
343
344 StringBuilder r = new StringBuilder();
345 r.append("Tree={");
346 if (!p.eof()) {
347 r.append('\n');
348 try {
349 new ObjectChecker().checkTree(raw);
350 } catch (CorruptObjectException error) {
351 r.append("*** ERROR: ").append(error.getMessage()).append("\n");
352 r.append('\n');
353 }
354 }
355 while (!p.eof()) {
356 final FileMode mode = p.getEntryFileMode();
357 r.append(mode);
358 r.append(' ');
359 r.append(Constants.typeString(mode.getObjectType()));
360 r.append(' ');
361 r.append(p.getEntryObjectId().name());
362 r.append(' ');
363 r.append(p.getEntryPathString());
364 r.append('\n');
365 p.next();
366 }
367 r.append("}");
368 return r.toString();
369 }
370 }