Consolidate the string type decoding into Constants
[egit/zawir.git] / org.spearce.jgit / src / org / spearce / jgit / lib / Constants.java
blobbf97fe0541f680ea44116fb3d0837757a1e95c4c
1 /*
2 * Copyright (C) 2006 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org.spearce.jgit.lib;
19 import java.nio.charset.Charset;
20 import java.security.MessageDigest;
21 import java.security.NoSuchAlgorithmException;
23 import org.spearce.jgit.errors.CorruptObjectException;
24 import org.spearce.jgit.util.MutableInteger;
26 /** Misc. constants used throughout JGit. */
27 public final class Constants {
28 /** Hash function used natively by Git for all objects. */
29 private static final String HASH_FUNCTION = "SHA-1";
31 /** Length of an object hash. */
32 public static final int OBJECT_ID_LENGTH = 20;
34 /** Special name for the "HEAD" symbolic-ref. */
35 public static final String HEAD = "HEAD";
37 /**
38 * Text string that identifies an object as a commit.
39 * <p>
40 * Commits connect trees into a string of project histories, where each
41 * commit is an assertion that the best way to continue is to use this other
42 * tree (set of files).
44 public static final String TYPE_COMMIT = "commit";
46 /**
47 * Text string that identifies an object as a blob.
48 * <p>
49 * Blobs store whole file revisions. They are used for any user file, as
50 * well as for symlinks. Blobs form the bulk of any project's storage space.
52 public static final String TYPE_BLOB = "blob";
54 /**
55 * Text string that identifies an object as a tree.
56 * <p>
57 * Trees attach object ids (hashes) to names and file modes. The normal use
58 * for a tree is to store a version of a directory and its contents.
60 public static final String TYPE_TREE = "tree";
62 /**
63 * Text string that identifies an object as an annotated tag.
64 * <p>
65 * Annotated tags store a pointer to any other object, and an additional
66 * message. It is most commonly used to record a stable release of the
67 * project.
69 public static final String TYPE_TAG = "tag";
71 private static final byte[] ENCODED_TYPE_COMMIT = encodeASCII(TYPE_COMMIT);
73 private static final byte[] ENCODED_TYPE_BLOB = encodeASCII(TYPE_BLOB);
75 private static final byte[] ENCODED_TYPE_TREE = encodeASCII(TYPE_TREE);
77 private static final byte[] ENCODED_TYPE_TAG = encodeASCII(TYPE_TAG);
79 /** An unknown or invalid object type code. */
80 public static final int OBJ_BAD = -1;
82 /**
83 * In-pack object type: extended types.
84 * <p>
85 * This header code is reserved for future expansion. It is currently
86 * undefined/unsupported.
88 public static final int OBJ_EXT = 0;
90 /**
91 * In-pack object type: commit.
92 * <p>
93 * Indicates the associated object is a commit.
94 * <p>
95 * <b>This constant is fixed and is defined by the Git packfile format.</b>
97 * @see #TYPE_COMMIT
99 public static final int OBJ_COMMIT = 1;
102 * In-pack object type: tree.
103 * <p>
104 * Indicates the associated object is a tree.
105 * <p>
106 * <b>This constant is fixed and is defined by the Git packfile format.</b>
108 * @see #TYPE_BLOB
110 public static final int OBJ_TREE = 2;
113 * In-pack object type: blob.
114 * <p>
115 * Indicates the associated object is a blob.
116 * <p>
117 * <b>This constant is fixed and is defined by the Git packfile format.</b>
119 * @see #TYPE_BLOB
121 public static final int OBJ_BLOB = 3;
124 * In-pack object type: annotated tag.
125 * <p>
126 * Indicates the associated object is an annotated tag.
127 * <p>
128 * <b>This constant is fixed and is defined by the Git packfile format.</b>
130 * @see #TYPE_TAG
132 public static final int OBJ_TAG = 4;
134 /** In-pack object type: reserved for future use. */
135 public static final int OBJ_TYPE_5 = 5;
138 * In-pack object type: offset delta
139 * <p>
140 * Objects stored with this type actually have a different type which must
141 * be obtained from their delta base object. Delta objects store only the
142 * changes needed to apply to the base object in order to recover the
143 * original object.
144 * <p>
145 * An offset delta uses a negative offset from the start of this object to
146 * refer to its delta base. The base object must exist in this packfile
147 * (even in the case of a thin pack).
148 * <p>
149 * <b>This constant is fixed and is defined by the Git packfile format.</b>
151 public static final int OBJ_OFS_DELTA = 6;
154 * In-pack object type: reference delta
155 * <p>
156 * Objects stored with this type actually have a different type which must
157 * be obtained from their delta base object. Delta objects store only the
158 * changes needed to apply to the base object in order to recover the
159 * original object.
160 * <p>
161 * A reference delta uses a full object id (hash) to reference the delta
162 * base. The base object is allowed to be omitted from the packfile, but
163 * only in the case of a thin pack being transferred over the network.
164 * <p>
165 * <b>This constant is fixed and is defined by the Git packfile format.</b>
167 public static final int OBJ_REF_DELTA = 7;
169 /** Native character encoding for commit messages, file names... */
170 public static final String CHARACTER_ENCODING = "UTF-8";
172 /** Native character encoding for commit messages, file names... */
173 public static final Charset CHARSET;
175 /** Default main branch name */
176 public static final String MASTER = "master";
178 /** Prefix for branch refs */
179 public static final String HEADS_PREFIX = "refs/heads";
181 /** Prefix for remotes refs */
182 public static final String REMOTES_PREFIX = "refs/remotes";
184 /** Prefix for tag refs */
185 public static final String TAGS_PREFIX = "refs/tags";
188 * Create a new digest function for objects.
190 * @return a new digest object.
191 * @throws RuntimeException
192 * this Java virtual machine does not support the required hash
193 * function. Very unlikely given that JGit uses a hash function
194 * that is in the Java reference specification.
196 public static MessageDigest newMessageDigest() {
197 try {
198 return MessageDigest.getInstance(HASH_FUNCTION);
199 } catch (NoSuchAlgorithmException nsae) {
200 throw new RuntimeException("Required hash function "
201 + HASH_FUNCTION + " not available.", nsae);
206 * Convert an OBJ_* type constant to a TYPE_* type constant.
208 * @param typeCode the type code, from a pack representation.
209 * @return the canonical string name of this type.
211 public static String typeString(final int typeCode) {
212 switch (typeCode) {
213 case OBJ_COMMIT:
214 return TYPE_COMMIT;
215 case OBJ_TREE:
216 return TYPE_TREE;
217 case OBJ_BLOB:
218 return TYPE_BLOB;
219 case OBJ_TAG:
220 return TYPE_TAG;
221 default:
222 throw new IllegalArgumentException("Bad object type: " + typeCode);
227 * Convert an OBJ_* type constant to an ASCII encoded string constant.
228 * <p>
229 * The ASCII encoded string is often the canonical representation of
230 * the type within a loose object header, or within a tag header.
232 * @param typeCode the type code, from a pack representation.
233 * @return the canonical ASCII encoded name of this type.
235 public static byte[] encodedTypeString(final int typeCode) {
236 switch (typeCode) {
237 case OBJ_COMMIT:
238 return ENCODED_TYPE_COMMIT;
239 case OBJ_TREE:
240 return ENCODED_TYPE_TREE;
241 case OBJ_BLOB:
242 return ENCODED_TYPE_BLOB;
243 case OBJ_TAG:
244 return ENCODED_TYPE_TAG;
245 default:
246 throw new IllegalArgumentException("Bad object type: " + typeCode);
251 * Parse an encoded type string into a type constant.
253 * @param id
254 * object id this type string came from; may be null if that is
255 * not known at the time the parse is occurring.
256 * @param typeString
257 * string version of the type code.
258 * @param endMark
259 * character immediately following the type string. Usually ' '
260 * (space) or '\n' (line feed).
261 * @param offset
262 * position within <code>typeString</code> where the parse
263 * should start. Updated with the new position (just past
264 * <code>endMark</code> when the parse is successful.
265 * @return a type code constant (one of {@link #OBJ_BLOB},
266 * {@link #OBJ_COMMIT}, {@link #OBJ_TAG}, {@link #OBJ_TREE}.
267 * @throws CorruptObjectException
268 * there is no valid type identified by <code>typeString</code>.
270 public static int decodeTypeString(final ObjectId id,
271 final byte[] typeString, final byte endMark,
272 final MutableInteger offset) throws CorruptObjectException {
273 try {
274 int position = offset.value;
275 switch (typeString[position]) {
276 case 'b':
277 if (typeString[position + 1] != 'l'
278 || typeString[position + 2] != 'o'
279 || typeString[position + 3] != 'b'
280 || typeString[position + 4] != endMark)
281 throw new CorruptObjectException(id, "invalid type");
282 offset.value = position + 5;
283 return Constants.OBJ_BLOB;
285 case 'c':
286 if (typeString[position + 1] != 'o'
287 || typeString[position + 2] != 'm'
288 || typeString[position + 3] != 'm'
289 || typeString[position + 4] != 'i'
290 || typeString[position + 5] != 't'
291 || typeString[position + 6] != endMark)
292 throw new CorruptObjectException(id, "invalid type");
293 offset.value = position + 7;
294 return Constants.OBJ_COMMIT;
296 case 't':
297 switch (typeString[position + 1]) {
298 case 'a':
299 if (typeString[position + 2] != 'g'
300 || typeString[position + 3] != endMark)
301 throw new CorruptObjectException(id, "invalid type");
302 offset.value = position + 4;
303 return Constants.OBJ_TAG;
305 case 'r':
306 if (typeString[position + 2] != 'e'
307 || typeString[position + 3] != 'e'
308 || typeString[position + 4] != endMark)
309 throw new CorruptObjectException(id, "invalid type");
310 offset.value = position + 5;
311 return Constants.OBJ_TREE;
313 default:
314 throw new CorruptObjectException(id, "invalid type");
317 default:
318 throw new CorruptObjectException(id, "invalid type");
320 } catch (ArrayIndexOutOfBoundsException bad) {
321 throw new CorruptObjectException(id, "invalid type");
326 * Convert an integer into its decimal representation.
328 * @param s
329 * the integer to convert.
330 * @return a decimal representation of the input integer. The returned array
331 * is the smallest array that will hold the value.
333 public static byte[] encodeASCII(final long s) {
334 return encodeASCII(Long.toString(s));
338 * Convert a string to US-ASCII encoding.
340 * @param s
341 * the string to convert. Must not contain any characters over
342 * 127 (outside of 7-bit ASCII).
343 * @return a byte array of the same length as the input string, holding the
344 * same characters, in the same order.
345 * @throws IllegalArgumentException
346 * the input string contains one or more characters outside of
347 * the 7-bit ASCII character space.
349 public static byte[] encodeASCII(final String s) {
350 final byte[] r = new byte[s.length()];
351 for (int k = r.length - 1; k >= 0; k--) {
352 final char c = s.charAt(k);
353 if (c > 127)
354 throw new IllegalArgumentException("Not ASCII string: " + s);
355 r[k] = (byte) c;
357 return r;
360 static {
361 if (OBJECT_ID_LENGTH != newMessageDigest().getDigestLength())
362 throw new LinkageError("Incorrect OBJECT_ID_LENGTH.");
363 CHARSET = Charset.forName(CHARACTER_ENCODING);
366 private Constants() {
367 // Hide the default constructor