| /* |
| * Copyright (C) 2008, Google Inc. |
| * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> |
| * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> |
| * and other copyright owners as documented in the project's IP log. |
| * |
| * This program and the accompanying materials are made available |
| * under the terms of the Eclipse Distribution License v1.0 which |
| * accompanies this distribution, is reproduced below, and is |
| * available at http://www.eclipse.org/org/documents/edl-v10.php |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or |
| * without modification, are permitted provided that the following |
| * conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * |
| * - Neither the name of the Eclipse Foundation, Inc. nor the |
| * names of its contributors may be used to endorse or promote |
| * products derived from this software without specific prior |
| * written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
| * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.eclipse.jgit.lib; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.charset.Charset; |
| import java.security.MessageDigest; |
| import java.security.NoSuchAlgorithmException; |
| import java.text.MessageFormat; |
| |
| import org.eclipse.jgit.JGitText; |
| import org.eclipse.jgit.errors.CorruptObjectException; |
| import org.eclipse.jgit.util.MutableInteger; |
| |
| /** Misc. constants used throughout JGit. */ |
| public final class Constants { |
| /** Hash function used natively by Git for all objects. */ |
| private static final String HASH_FUNCTION = "SHA-1"; |
| |
| /** |
| * A Git object hash is 160 bits, i.e. 20 bytes. |
| * <p> |
| * Changing this assumption is not going to be as easy as changing this |
| * declaration. |
| */ |
| public static final int OBJECT_ID_LENGTH = 20; |
| |
| /** |
| * A Git object can be expressed as a 40 character string of hexadecimal |
| * digits. |
| * |
| * @see #OBJECT_ID_LENGTH |
| */ |
| public static final int OBJECT_ID_STRING_LENGTH = OBJECT_ID_LENGTH * 2; |
| |
| /** Special name for the "HEAD" symbolic-ref. */ |
| public static final String HEAD = "HEAD"; |
| |
| /** Special name for the "FETCH_HEAD" symbolic-ref. */ |
| public static final String FETCH_HEAD = "FETCH_HEAD"; |
| |
| /** |
| * Text string that identifies an object as a commit. |
| * <p> |
| * Commits connect trees into a string of project histories, where each |
| * commit is an assertion that the best way to continue is to use this other |
| * tree (set of files). |
| */ |
| public static final String TYPE_COMMIT = "commit"; |
| |
| /** |
| * Text string that identifies an object as a blob. |
| * <p> |
| * Blobs store whole file revisions. They are used for any user file, as |
| * well as for symlinks. Blobs form the bulk of any project's storage space. |
| */ |
| public static final String TYPE_BLOB = "blob"; |
| |
| /** |
| * Text string that identifies an object as a tree. |
| * <p> |
| * Trees attach object ids (hashes) to names and file modes. The normal use |
| * for a tree is to store a version of a directory and its contents. |
| */ |
| public static final String TYPE_TREE = "tree"; |
| |
| /** |
| * Text string that identifies an object as an annotated tag. |
| * <p> |
| * Annotated tags store a pointer to any other object, and an additional |
| * message. It is most commonly used to record a stable release of the |
| * project. |
| */ |
| public static final String TYPE_TAG = "tag"; |
| |
| private static final byte[] ENCODED_TYPE_COMMIT = encodeASCII(TYPE_COMMIT); |
| |
| private static final byte[] ENCODED_TYPE_BLOB = encodeASCII(TYPE_BLOB); |
| |
| private static final byte[] ENCODED_TYPE_TREE = encodeASCII(TYPE_TREE); |
| |
| private static final byte[] ENCODED_TYPE_TAG = encodeASCII(TYPE_TAG); |
| |
| /** An unknown or invalid object type code. */ |
| public static final int OBJ_BAD = -1; |
| |
| /** |
| * In-pack object type: extended types. |
| * <p> |
| * This header code is reserved for future expansion. It is currently |
| * undefined/unsupported. |
| */ |
| public static final int OBJ_EXT = 0; |
| |
| /** |
| * In-pack object type: commit. |
| * <p> |
| * Indicates the associated object is a commit. |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| * |
| * @see #TYPE_COMMIT |
| */ |
| public static final int OBJ_COMMIT = 1; |
| |
| /** |
| * In-pack object type: tree. |
| * <p> |
| * Indicates the associated object is a tree. |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| * |
| * @see #TYPE_BLOB |
| */ |
| public static final int OBJ_TREE = 2; |
| |
| /** |
| * In-pack object type: blob. |
| * <p> |
| * Indicates the associated object is a blob. |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| * |
| * @see #TYPE_BLOB |
| */ |
| public static final int OBJ_BLOB = 3; |
| |
| /** |
| * In-pack object type: annotated tag. |
| * <p> |
| * Indicates the associated object is an annotated tag. |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| * |
| * @see #TYPE_TAG |
| */ |
| public static final int OBJ_TAG = 4; |
| |
| /** In-pack object type: reserved for future use. */ |
| public static final int OBJ_TYPE_5 = 5; |
| |
| /** |
| * In-pack object type: offset delta |
| * <p> |
| * Objects stored with this type actually have a different type which must |
| * be obtained from their delta base object. Delta objects store only the |
| * changes needed to apply to the base object in order to recover the |
| * original object. |
| * <p> |
| * An offset delta uses a negative offset from the start of this object to |
| * refer to its delta base. The base object must exist in this packfile |
| * (even in the case of a thin pack). |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| */ |
| public static final int OBJ_OFS_DELTA = 6; |
| |
| /** |
| * In-pack object type: reference delta |
| * <p> |
| * Objects stored with this type actually have a different type which must |
| * be obtained from their delta base object. Delta objects store only the |
| * changes needed to apply to the base object in order to recover the |
| * original object. |
| * <p> |
| * A reference delta uses a full object id (hash) to reference the delta |
| * base. The base object is allowed to be omitted from the packfile, but |
| * only in the case of a thin pack being transferred over the network. |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| */ |
| public static final int OBJ_REF_DELTA = 7; |
| |
| /** |
| * Pack file signature that occurs at file header - identifies file as Git |
| * packfile formatted. |
| * <p> |
| * <b>This constant is fixed and is defined by the Git packfile format.</b> |
| */ |
| public static final byte[] PACK_SIGNATURE = { 'P', 'A', 'C', 'K' }; |
| |
| /** Native character encoding for commit messages, file names... */ |
| public static final String CHARACTER_ENCODING = "UTF-8"; |
| |
| /** Native character encoding for commit messages, file names... */ |
| public static final Charset CHARSET; |
| |
| /** Default main branch name */ |
| public static final String MASTER = "master"; |
| |
| /** Prefix for branch refs */ |
| public static final String R_HEADS = "refs/heads/"; |
| |
| /** Prefix for remotes refs */ |
| public static final String R_REMOTES = "refs/remotes/"; |
| |
| /** Prefix for tag refs */ |
| public static final String R_TAGS = "refs/tags/"; |
| |
| /** Prefix for any ref */ |
| public static final String R_REFS = "refs/"; |
| |
| /** Logs folder name */ |
| public static final String LOGS = "logs"; |
| |
| /** Info refs folder */ |
| public static final String INFO_REFS = "info/refs"; |
| |
| /** Packed refs file */ |
| public static final String PACKED_REFS = "packed-refs"; |
| |
| /** The environment variable that contains the system user name */ |
| public static final String OS_USER_NAME_KEY = "user.name"; |
| |
| /** The environment variable that contains the author's name */ |
| public static final String GIT_AUTHOR_NAME_KEY = "GIT_AUTHOR_NAME"; |
| |
| /** The environment variable that contains the author's email */ |
| public static final String GIT_AUTHOR_EMAIL_KEY = "GIT_AUTHOR_EMAIL"; |
| |
| /** The environment variable that contains the commiter's name */ |
| public static final String GIT_COMMITTER_NAME_KEY = "GIT_COMMITTER_NAME"; |
| |
| /** The environment variable that contains the commiter's email */ |
| public static final String GIT_COMMITTER_EMAIL_KEY = "GIT_COMMITTER_EMAIL"; |
| |
| /** |
| * The environment variable that limits how close to the root of the file |
| * systems JGit will traverse when looking for a repository root. |
| */ |
| public static final String GIT_CEILING_DIRECTORIES_KEY = "GIT_CEILING_DIRECTORIES"; |
| |
| /** |
| * The environment variable that tells us which directory is the ".git" |
| * directory |
| */ |
| public static final String GIT_DIR_KEY = "GIT_DIR"; |
| |
| /** |
| * The environment variable that tells us which directory is the working |
| * directory. |
| */ |
| public static final String GIT_WORK_TREE_KEY = "GIT_WORK_TREE"; |
| |
| /** |
| * The environment variable that tells us which file holds the Git index. |
| */ |
| public static final String GIT_INDEX_KEY = "GIT_INDEX"; |
| |
| /** |
| * The environment variable that tells us where objects are stored |
| */ |
| public static final String GIT_OBJECT_DIRECTORY_KEY = "GIT_OBJECT_DIRECTORY"; |
| |
| /** |
| * The environment variable that tells us where to look for objects, besides |
| * the default objects directory. |
| */ |
| public static final String GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY = "GIT_ALTERNATE_OBJECT_DIRECTORIES"; |
| |
| /** Default value for the user name if no other information is available */ |
| public static final String UNKNOWN_USER_DEFAULT = "unknown-user"; |
| |
| /** Beginning of the common "Signed-off-by: " commit message line */ |
| public static final String SIGNED_OFF_BY_TAG = "Signed-off-by: "; |
| |
| /** A gitignore file name */ |
| public static final String GITIGNORE_FILENAME = ".gitignore"; |
| |
| /** Default remote name used by clone, push and fetch operations */ |
| public static final String DEFAULT_REMOTE_NAME = "origin"; |
| |
| /** Default name for the Git repository directory */ |
| public static final String DOT_GIT = ".git"; |
| |
| /** A bare repository typically ends with this string */ |
| public static final String DOT_GIT_EXT = ".git"; |
| |
| /** Name of the ignore file */ |
| public static final String DOT_GIT_IGNORE = ".gitignore"; |
| |
| /** |
| * Create a new digest function for objects. |
| * |
| * @return a new digest object. |
| * @throws RuntimeException |
| * this Java virtual machine does not support the required hash |
| * function. Very unlikely given that JGit uses a hash function |
| * that is in the Java reference specification. |
| */ |
| public static MessageDigest newMessageDigest() { |
| try { |
| return MessageDigest.getInstance(HASH_FUNCTION); |
| } catch (NoSuchAlgorithmException nsae) { |
| throw new RuntimeException(MessageFormat.format( |
| JGitText.get().requiredHashFunctionNotAvailable, HASH_FUNCTION), nsae); |
| } |
| } |
| |
| /** |
| * Convert an OBJ_* type constant to a TYPE_* type constant. |
| * |
| * @param typeCode the type code, from a pack representation. |
| * @return the canonical string name of this type. |
| */ |
| public static String typeString(final int typeCode) { |
| switch (typeCode) { |
| case OBJ_COMMIT: |
| return TYPE_COMMIT; |
| case OBJ_TREE: |
| return TYPE_TREE; |
| case OBJ_BLOB: |
| return TYPE_BLOB; |
| case OBJ_TAG: |
| return TYPE_TAG; |
| default: |
| throw new IllegalArgumentException(MessageFormat.format(JGitText.get().badObjectType, typeCode)); |
| } |
| } |
| |
| /** |
| * Convert an OBJ_* type constant to an ASCII encoded string constant. |
| * <p> |
| * The ASCII encoded string is often the canonical representation of |
| * the type within a loose object header, or within a tag header. |
| * |
| * @param typeCode the type code, from a pack representation. |
| * @return the canonical ASCII encoded name of this type. |
| */ |
| public static byte[] encodedTypeString(final int typeCode) { |
| switch (typeCode) { |
| case OBJ_COMMIT: |
| return ENCODED_TYPE_COMMIT; |
| case OBJ_TREE: |
| return ENCODED_TYPE_TREE; |
| case OBJ_BLOB: |
| return ENCODED_TYPE_BLOB; |
| case OBJ_TAG: |
| return ENCODED_TYPE_TAG; |
| default: |
| throw new IllegalArgumentException(MessageFormat.format(JGitText.get().badObjectType, typeCode)); |
| } |
| } |
| |
| /** |
| * Parse an encoded type string into a type constant. |
| * |
| * @param id |
| * object id this type string came from; may be null if that is |
| * not known at the time the parse is occurring. |
| * @param typeString |
| * string version of the type code. |
| * @param endMark |
| * character immediately following the type string. Usually ' ' |
| * (space) or '\n' (line feed). |
| * @param offset |
| * position within <code>typeString</code> where the parse |
| * should start. Updated with the new position (just past |
| * <code>endMark</code> when the parse is successful. |
| * @return a type code constant (one of {@link #OBJ_BLOB}, |
| * {@link #OBJ_COMMIT}, {@link #OBJ_TAG}, {@link #OBJ_TREE}. |
| * @throws CorruptObjectException |
| * there is no valid type identified by <code>typeString</code>. |
| */ |
| public static int decodeTypeString(final AnyObjectId id, |
| final byte[] typeString, final byte endMark, |
| final MutableInteger offset) throws CorruptObjectException { |
| try { |
| int position = offset.value; |
| switch (typeString[position]) { |
| case 'b': |
| if (typeString[position + 1] != 'l' |
| || typeString[position + 2] != 'o' |
| || typeString[position + 3] != 'b' |
| || typeString[position + 4] != endMark) |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| offset.value = position + 5; |
| return Constants.OBJ_BLOB; |
| |
| case 'c': |
| if (typeString[position + 1] != 'o' |
| || typeString[position + 2] != 'm' |
| || typeString[position + 3] != 'm' |
| || typeString[position + 4] != 'i' |
| || typeString[position + 5] != 't' |
| || typeString[position + 6] != endMark) |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| offset.value = position + 7; |
| return Constants.OBJ_COMMIT; |
| |
| case 't': |
| switch (typeString[position + 1]) { |
| case 'a': |
| if (typeString[position + 2] != 'g' |
| || typeString[position + 3] != endMark) |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| offset.value = position + 4; |
| return Constants.OBJ_TAG; |
| |
| case 'r': |
| if (typeString[position + 2] != 'e' |
| || typeString[position + 3] != 'e' |
| || typeString[position + 4] != endMark) |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| offset.value = position + 5; |
| return Constants.OBJ_TREE; |
| |
| default: |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| } |
| |
| default: |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| } |
| } catch (ArrayIndexOutOfBoundsException bad) { |
| throw new CorruptObjectException(id, JGitText.get().corruptObjectInvalidType); |
| } |
| } |
| |
| /** |
| * Convert an integer into its decimal representation. |
| * |
| * @param s |
| * the integer to convert. |
| * @return a decimal representation of the input integer. The returned array |
| * is the smallest array that will hold the value. |
| */ |
| public static byte[] encodeASCII(final long s) { |
| return encodeASCII(Long.toString(s)); |
| } |
| |
| /** |
| * Convert a string to US-ASCII encoding. |
| * |
| * @param s |
| * the string to convert. Must not contain any characters over |
| * 127 (outside of 7-bit ASCII). |
| * @return a byte array of the same length as the input string, holding the |
| * same characters, in the same order. |
| * @throws IllegalArgumentException |
| * the input string contains one or more characters outside of |
| * the 7-bit ASCII character space. |
| */ |
| public static byte[] encodeASCII(final String s) { |
| final byte[] r = new byte[s.length()]; |
| for (int k = r.length - 1; k >= 0; k--) { |
| final char c = s.charAt(k); |
| if (c > 127) |
| throw new IllegalArgumentException(MessageFormat.format(JGitText.get().notASCIIString, s)); |
| r[k] = (byte) c; |
| } |
| return r; |
| } |
| |
| /** |
| * Convert a string to a byte array in the standard character encoding. |
| * |
| * @param str |
| * the string to convert. May contain any Unicode characters. |
| * @return a byte array representing the requested string, encoded using the |
| * default character encoding (UTF-8). |
| * @see #CHARACTER_ENCODING |
| */ |
| public static byte[] encode(final String str) { |
| final ByteBuffer bb = Constants.CHARSET.encode(str); |
| final int len = bb.limit(); |
| if (bb.hasArray() && bb.arrayOffset() == 0) { |
| final byte[] arr = bb.array(); |
| if (arr.length == len) |
| return arr; |
| } |
| |
| final byte[] arr = new byte[len]; |
| bb.get(arr); |
| return arr; |
| } |
| |
| static { |
| if (OBJECT_ID_LENGTH != newMessageDigest().getDigestLength()) |
| throw new LinkageError(JGitText.get().incorrectOBJECT_ID_LENGTH); |
| CHARSET = Charset.forName(CHARACTER_ENCODING); |
| } |
| |
| /** name of the file containing the commit msg for a merge commit */ |
| public static final String MERGE_MSG = "MERGE_MSG"; |
| |
| /** name of the file containing the IDs of the parents of a merge commit */ |
| public static final String MERGE_HEAD = "MERGE_HEAD"; |
| |
| /** |
| * name of the ref ORIG_HEAD used by certain commands to store the original |
| * value of HEAD |
| */ |
| public static final String ORIG_HEAD = "ORIG_HEAD"; |
| |
| /** objectid for the empty blob */ |
| public static final ObjectId EMPTY_BLOB_ID = ObjectId |
| .fromString("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"); |
| |
| private Constants() { |
| // Hide the default constructor |
| } |
| } |