1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jgit.revwalk;
14
15 import static java.nio.charset.StandardCharsets.UTF_8;
16
17 import java.io.IOException;
18 import java.nio.charset.Charset;
19 import java.nio.charset.IllegalCharsetNameException;
20 import java.nio.charset.UnsupportedCharsetException;
21 import java.util.Arrays;
22
23 import org.eclipse.jgit.annotations.Nullable;
24 import org.eclipse.jgit.errors.CorruptObjectException;
25 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
26 import org.eclipse.jgit.errors.MissingObjectException;
27 import org.eclipse.jgit.lib.AnyObjectId;
28 import org.eclipse.jgit.lib.Constants;
29 import org.eclipse.jgit.lib.ObjectInserter;
30 import org.eclipse.jgit.lib.ObjectReader;
31 import org.eclipse.jgit.lib.PersonIdent;
32 import org.eclipse.jgit.util.MutableInteger;
33 import org.eclipse.jgit.util.RawParseUtils;
34 import org.eclipse.jgit.util.StringUtils;
35
36
37
38
39 public class RevTag extends RevObject {
40
41 private static final byte[] hSignature = Constants
42 .encodeASCII("-----BEGIN PGP SIGNATURE-----");
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public static RevTag parse(byte[] raw) throws CorruptObjectException {
65 return parse(new RevWalk((ObjectReader) null), raw);
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 public static RevTag parse(RevWalk rw, byte[] raw)
92 throws CorruptObjectException {
93 try (ObjectInserter.Formatter fmt = new ObjectInserter.Formatter()) {
94 RevTag r = rw.lookupTag(fmt.idFor(Constants.OBJ_TAG, raw));
95 r.parseCanonical(rw, raw);
96 r.buffer = raw;
97 return r;
98 }
99 }
100
101 private RevObject object;
102
103 private byte[] buffer;
104
105 private String tagName;
106
107
108
109
110
111
112
113 protected RevTag(AnyObjectId id) {
114 super(id);
115 }
116
117 @Override
118 void parseHeaders(RevWalk walk) throws MissingObjectException,
119 IncorrectObjectTypeException, IOException {
120 parseCanonical(walk, walk.getCachedBytes(this));
121 }
122
123 @Override
124 void parseBody(RevWalk walk) throws MissingObjectException,
125 IncorrectObjectTypeException, IOException {
126 if (buffer == null) {
127 buffer = walk.getCachedBytes(this);
128 if ((flags & PARSED) == 0)
129 parseCanonical(walk, buffer);
130 }
131 }
132
133 void parseCanonical(RevWalk walk, byte[] rawTag)
134 throws CorruptObjectException {
135 final MutableIntegerger.html#MutableInteger">MutableInteger pos = new MutableInteger();
136 final int oType;
137
138 pos.value = 53;
139 oType = Constants.decodeTypeString(this, rawTag, (byte) '\n', pos);
140 walk.idBuffer.fromString(rawTag, 7);
141 object = walk.lookupAny(walk.idBuffer, oType);
142
143 int p = pos.value += 4;
144 final int nameEnd = RawParseUtils.nextLF(rawTag, p) - 1;
145 tagName = RawParseUtils.decode(UTF_8, rawTag, p, nameEnd);
146
147 if (walk.isRetainBody())
148 buffer = rawTag;
149 flags |= PARSED;
150 }
151
152
153 @Override
154 public final int getType() {
155 return Constants.OBJ_TAG;
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public final PersonIdent getTaggerIdent() {
173 final byte[] raw = buffer;
174 final int nameB = RawParseUtils.tagger(raw, 0);
175 if (nameB < 0)
176 return null;
177 return RawParseUtils.parsePersonIdent(raw, nameB);
178 }
179
180 private static int nextStart(byte[] prefix, byte[] buffer, int from) {
181 int stop = buffer.length - prefix.length + 1;
182 int ptr = from;
183 if (ptr > 0) {
184 ptr = RawParseUtils.nextLF(buffer, ptr - 1);
185 }
186 while (ptr < stop) {
187 int lineStart = ptr;
188 boolean found = true;
189 for (byte element : prefix) {
190 if (element != buffer[ptr++]) {
191 found = false;
192 break;
193 }
194 }
195 if (found) {
196 return lineStart;
197 }
198 do {
199 ptr = RawParseUtils.nextLF(buffer, ptr);
200 } while (ptr < stop && buffer[ptr] == '\n');
201 }
202 return -1;
203 }
204
205 private int getSignatureStart() {
206 byte[] raw = buffer;
207 int msgB = RawParseUtils.tagMessage(raw, 0);
208 if (msgB < 0) {
209 return msgB;
210 }
211
212 int start = nextStart(hSignature, raw, msgB);
213 if (start < 0) {
214 return start;
215 }
216 int next = RawParseUtils.nextLF(raw, start);
217 while (next < raw.length) {
218 int newStart = nextStart(hSignature, raw, next);
219 if (newStart < 0) {
220 break;
221 }
222 start = newStart;
223 next = RawParseUtils.nextLF(raw, start);
224 }
225 return start;
226 }
227
228
229
230
231
232
233
234
235 @Nullable
236 public final byte[] getRawGpgSignature() {
237 byte[] raw = buffer;
238 int start = getSignatureStart();
239 if (start < 0) {
240 return null;
241 }
242 return Arrays.copyOfRange(raw, start, raw.length);
243 }
244
245
246
247
248
249
250
251
252
253
254
255 public final String getFullMessage() {
256 byte[] raw = buffer;
257 int msgB = RawParseUtils.tagMessage(raw, 0);
258 if (msgB < 0) {
259 return "";
260 }
261 int signatureStart = getSignatureStart();
262 int end = signatureStart < 0 ? raw.length : signatureStart;
263 if (end == msgB) {
264 return "";
265 }
266 return RawParseUtils.decode(guessEncoding(), raw, msgB, end);
267 }
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284 public final String getShortMessage() {
285 byte[] raw = buffer;
286 int msgB = RawParseUtils.tagMessage(raw, 0);
287 if (msgB < 0) {
288 return "";
289 }
290
291 int msgE = RawParseUtils.endOfParagraph(raw, msgB);
292 int signatureStart = getSignatureStart();
293 if (signatureStart >= msgB && msgE > signatureStart) {
294 msgE = signatureStart;
295 if (msgE > msgB) {
296 msgE--;
297 }
298 if (msgB == msgE) {
299 return "";
300 }
301 }
302 String str = RawParseUtils.decode(guessEncoding(), raw, msgB, msgE);
303 if (RevCommit.hasLF(raw, msgB, msgE)) {
304 str = StringUtils.replaceLineBreaksWithSpace(str);
305 }
306 return str;
307 }
308
309 private Charset guessEncoding() {
310 try {
311 return RawParseUtils.parseEncoding(buffer);
312 } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
313 return UTF_8;
314 }
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333 public final RevObject getObject() {
334 return object;
335 }
336
337
338
339
340
341
342 public final String getTagName() {
343 return tagName;
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357
358 public final byte[] getRawBuffer() {
359 return buffer;
360 }
361
362
363
364
365
366
367
368
369
370
371
372
373 public final void disposeBody() {
374 buffer = null;
375 }
376 }