/*
 * Copyright (C) 2008-2009, Google Inc.
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * Copyright (C) 2010, Matthias Sohn <matthias.sohn@sap.com>
 * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
 * 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.dircache;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.Arrays;

import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.MutableInteger;
import org.eclipse.jgit.util.NB;
import org.eclipse.jgit.util.SystemReader;

/**
 * A single file (or stage of a file) in a
 * {@link org.eclipse.jgit.dircache.DirCache}.
 * <p>
 * An entry represents exactly one stage of a file. If a file path is unmerged
 * then multiple DirCacheEntry instances may appear for the same path name.
 */
public class DirCacheEntry {
	private static final byte[] nullpad = new byte[8];

	/** The standard (fully merged) stage for an entry. */
	public static final int STAGE_0 = 0;

	/** The base tree revision for an entry. */
	public static final int STAGE_1 = 1;

	/** The first tree revision (usually called "ours"). */
	public static final int STAGE_2 = 2;

	/** The second tree revision (usually called "theirs"). */
	public static final int STAGE_3 = 3;

	private static final int P_CTIME = 0;

	// private static final int P_CTIME_NSEC = 4;

	private static final int P_MTIME = 8;

	// private static final int P_MTIME_NSEC = 12;

	// private static final int P_DEV = 16;

	// private static final int P_INO = 20;

	private static final int P_MODE = 24;

	// private static final int P_UID = 28;

	// private static final int P_GID = 32;

	private static final int P_SIZE = 36;

	private static final int P_OBJECTID = 40;

	private static final int P_FLAGS = 60;
	private static final int P_FLAGS2 = 62;

	/** Mask applied to data in {@link #P_FLAGS} to get the name length. */
	private static final int NAME_MASK = 0xfff;

	private static final int INTENT_TO_ADD = 0x20000000;
	private static final int SKIP_WORKTREE = 0x40000000;
	private static final int EXTENDED_FLAGS = (INTENT_TO_ADD | SKIP_WORKTREE);

	private static final int INFO_LEN = 62;
	private static final int INFO_LEN_EXTENDED = 64;

	private static final int EXTENDED = 0x40;
	private static final int ASSUME_VALID = 0x80;

	/** In-core flag signaling that the entry should be considered as modified. */
	private static final int UPDATE_NEEDED = 0x1;

	/** (Possibly shared) header information storage. */
	private final byte[] info;

	/** First location within {@link #info} where our header starts. */
	private final int infoOffset;

	/** Our encoded path name, from the root of the repository. */
	final byte[] path;

	/** Flags which are never stored to disk. */
	private byte inCoreFlags;

	DirCacheEntry(final byte[] sharedInfo, final MutableInteger infoAt,
			final InputStream in, final MessageDigest md, final Instant smudge)
			throws IOException {
		info = sharedInfo;
		infoOffset = infoAt.value;

		IO.readFully(in, info, infoOffset, INFO_LEN);

		final int len;
		if (isExtended()) {
			len = INFO_LEN_EXTENDED;
			IO.readFully(in, info, infoOffset + INFO_LEN, INFO_LEN_EXTENDED - INFO_LEN);

			if ((getExtendedFlags() & ~EXTENDED_FLAGS) != 0)
				throw new IOException(MessageFormat.format(JGitText.get()
						.DIRCUnrecognizedExtendedFlags, String.valueOf(getExtendedFlags())));
		} else
			len = INFO_LEN;

		infoAt.value += len;
		md.update(info, infoOffset, len);

		int pathLen = NB.decodeUInt16(info, infoOffset + P_FLAGS) & NAME_MASK;
		int skipped = 0;
		if (pathLen < NAME_MASK) {
			path = new byte[pathLen];
			IO.readFully(in, path, 0, pathLen);
			md.update(path, 0, pathLen);
		} else {
			final ByteArrayOutputStream tmp = new ByteArrayOutputStream();
			{
				final byte[] buf = new byte[NAME_MASK];
				IO.readFully(in, buf, 0, NAME_MASK);
				tmp.write(buf);
			}
			for (;;) {
				final int c = in.read();
				if (c < 0)
					throw new EOFException(JGitText.get().shortReadOfBlock);
				if (c == 0)
					break;
				tmp.write(c);
			}
			path = tmp.toByteArray();
			pathLen = path.length;
			skipped = 1; // we already skipped 1 '\0' above to break the loop.
			md.update(path, 0, pathLen);
			md.update((byte) 0);
		}

		try {
			checkPath(path);
		} catch (InvalidPathException e) {
			CorruptObjectException p =
				new CorruptObjectException(e.getMessage());
			if (e.getCause() != null)
				p.initCause(e.getCause());
			throw p;
		}

		// Index records are padded out to the next 8 byte alignment
		// for historical reasons related to how C Git read the files.
		//
		final int actLen = len + pathLen;
		final int expLen = (actLen + 8) & ~7;
		final int padLen = expLen - actLen - skipped;
		if (padLen > 0) {
			IO.skipFully(in, padLen);
			md.update(nullpad, 0, padLen);
		}

		if (mightBeRacilyClean(smudge)) {
			smudgeRacilyClean();
		}
	}

	/**
	 * Create an empty entry at stage 0.
	 *
	 * @param newPath
	 *            name of the cache entry.
	 * @throws java.lang.IllegalArgumentException
	 *             If the path starts or ends with "/", or contains "//" either
	 *             "\0". These sequences are not permitted in a git tree object
	 *             or DirCache file.
	 */
	public DirCacheEntry(String newPath) {
		this(Constants.encode(newPath), STAGE_0);
	}

	/**
	 * Create an empty entry at the specified stage.
	 *
	 * @param newPath
	 *            name of the cache entry.
	 * @param stage
	 *            the stage index of the new entry.
	 * @throws java.lang.IllegalArgumentException
	 *             If the path starts or ends with "/", or contains "//" either
	 *             "\0". These sequences are not permitted in a git tree object
	 *             or DirCache file.  Or if {@code stage} is outside of the
	 *             range 0..3, inclusive.
	 */
	public DirCacheEntry(String newPath, int stage) {
		this(Constants.encode(newPath), stage);
	}

	/**
	 * Create an empty entry at stage 0.
	 *
	 * @param newPath
	 *            name of the cache entry, in the standard encoding.
	 * @throws java.lang.IllegalArgumentException
	 *             If the path starts or ends with "/", or contains "//" either
	 *             "\0". These sequences are not permitted in a git tree object
	 *             or DirCache file.
	 */
	public DirCacheEntry(byte[] newPath) {
		this(newPath, STAGE_0);
	}

	/**
	 * Create an empty entry at the specified stage.
	 *
	 * @param path
	 *            name of the cache entry, in the standard encoding.
	 * @param stage
	 *            the stage index of the new entry.
	 * @throws java.lang.IllegalArgumentException
	 *             If the path starts or ends with "/", or contains "//" either
	 *             "\0". These sequences are not permitted in a git tree object
	 *             or DirCache file.  Or if {@code stage} is outside of the
	 *             range 0..3, inclusive.
	 */
	@SuppressWarnings("boxing")
	public DirCacheEntry(byte[] path, int stage) {
		checkPath(path);
		if (stage < 0 || 3 < stage)
			throw new IllegalArgumentException(MessageFormat.format(
					JGitText.get().invalidStageForPath,
					stage, toString(path)));

		info = new byte[INFO_LEN];
		infoOffset = 0;
		this.path = path;

		int flags = ((stage & 0x3) << 12);
		if (path.length < NAME_MASK)
			flags |= path.length;
		else
			flags |= NAME_MASK;
		NB.encodeInt16(info, infoOffset + P_FLAGS, flags);
	}

	/**
	 * Duplicate DirCacheEntry with same path and copied info.
	 * <p>
	 * The same path buffer is reused (avoiding copying), however a new info
	 * buffer is created and its contents are copied.
	 *
	 * @param src
	 *            entry to clone.
	 * @since 4.2
	 */
	public DirCacheEntry(DirCacheEntry src) {
		path = src.path;
		info = new byte[INFO_LEN];
		infoOffset = 0;
		System.arraycopy(src.info, src.infoOffset, info, 0, INFO_LEN);
	}

	void write(OutputStream os) throws IOException {
		final int len = isExtended() ? INFO_LEN_EXTENDED : INFO_LEN;
		final int pathLen = path.length;
		os.write(info, infoOffset, len);
		os.write(path, 0, pathLen);

		// Index records are padded out to the next 8 byte alignment
		// for historical reasons related to how C Git read the files.
		//
		final int actLen = len + pathLen;
		final int expLen = (actLen + 8) & ~7;
		if (actLen != expLen)
			os.write(nullpad, 0, expLen - actLen);
	}

	/**
	 * Is it possible for this entry to be accidentally assumed clean?
	 * <p>
	 * The "racy git" problem happens when a work file can be updated faster
	 * than the filesystem records file modification timestamps. It is possible
	 * for an application to edit a work file, update the index, then edit it
	 * again before the filesystem will give the work file a new modification
	 * timestamp. This method tests to see if file was written out at the same
	 * time as the index.
	 *
	 * @param smudge_s
	 *            seconds component of the index's last modified time.
	 * @param smudge_ns
	 *            nanoseconds component of the index's last modified time.
	 * @return true if extra careful checks should be used.
	 * @deprecated use {@link #mightBeRacilyClean(Instant)} instead
	 */
	@Deprecated
	public final boolean mightBeRacilyClean(int smudge_s, int smudge_ns) {
		return mightBeRacilyClean(Instant.ofEpochSecond(smudge_s, smudge_ns));
	}

	/**
	 * Is it possible for this entry to be accidentally assumed clean?
	 * <p>
	 * The "racy git" problem happens when a work file can be updated faster
	 * than the filesystem records file modification timestamps. It is possible
	 * for an application to edit a work file, update the index, then edit it
	 * again before the filesystem will give the work file a new modification
	 * timestamp. This method tests to see if file was written out at the same
	 * time as the index.
	 *
	 * @param smudge
	 *            index's last modified time.
	 * @return true if extra careful checks should be used.
	 * @since 5.1.9
	 */
	public final boolean mightBeRacilyClean(Instant smudge) {
		// If the index has a modification time then it came from disk
		// and was not generated from scratch in memory. In such cases
		// the entry is 'racily clean' if the entry's cached modification
		// time is equal to or later than the index modification time. In
		// such cases the work file is too close to the index to tell if
		// it is clean or not based on the modification time alone.
		//
		final int base = infoOffset + P_MTIME;
		final int mtime = NB.decodeInt32(info, base);
		if ((int) smudge.getEpochSecond() == mtime) {
			return smudge.getNano() <= NB.decodeInt32(info, base + 4);
		}
		return false;
	}

	/**
	 * Force this entry to no longer match its working tree file.
	 * <p>
	 * This avoids the "racy git" problem by making this index entry no longer
	 * match the file in the working directory. Later git will be forced to
	 * compare the file content to ensure the file matches the working tree.
	 */
	public final void smudgeRacilyClean() {
		// To mark an entry racily clean we set its length to 0 (like native git
		// does). Entries which are not racily clean and have zero length can be
		// distinguished from racily clean entries by checking P_OBJECTID
		// against the SHA1 of empty content. When length is 0 and P_OBJECTID is
		// different from SHA1 of empty content we know the entry is marked
		// racily clean
		final int base = infoOffset + P_SIZE;
		Arrays.fill(info, base, base + 4, (byte) 0);
	}

	/**
	 * Check whether this entry has been smudged or not
	 * <p>
	 * If a blob has length 0 we know its id, see
	 * {@link org.eclipse.jgit.lib.Constants#EMPTY_BLOB_ID}. If an entry has
	 * length 0 and an ID different from the one for empty blob we know this
	 * entry was smudged.
	 *
	 * @return <code>true</code> if the entry is smudged, <code>false</code>
	 *         otherwise
	 */
	public final boolean isSmudged() {
		final int base = infoOffset + P_OBJECTID;
		return (getLength() == 0) && (Constants.EMPTY_BLOB_ID.compareTo(info, base) != 0);
	}

	final byte[] idBuffer() {
		return info;
	}

	final int idOffset() {
		return infoOffset + P_OBJECTID;
	}

	/**
	 * Is this entry always thought to be unmodified?
	 * <p>
	 * Most entries in the index do not have this flag set. Users may however
	 * set them on if the file system stat() costs are too high on this working
	 * directory, such as on NFS or SMB volumes.
	 *
	 * @return true if we must assume the entry is unmodified.
	 */
	public boolean isAssumeValid() {
		return (info[infoOffset + P_FLAGS] & ASSUME_VALID) != 0;
	}

	/**
	 * Set the assume valid flag for this entry,
	 *
	 * @param assume
	 *            true to ignore apparent modifications; false to look at last
	 *            modified to detect file modifications.
	 */
	public void setAssumeValid(boolean assume) {
		if (assume)
			info[infoOffset + P_FLAGS] |= ASSUME_VALID;
		else
			info[infoOffset + P_FLAGS] &= ~ASSUME_VALID;
	}

	/**
	 * Whether this entry should be checked for changes
	 *
	 * @return {@code true} if this entry should be checked for changes
	 */
	public boolean isUpdateNeeded() {
		return (inCoreFlags & UPDATE_NEEDED) != 0;
	}

	/**
	 * Set whether this entry must be checked for changes
	 *
	 * @param updateNeeded
	 *            whether this entry must be checked for changes
	 */
	public void setUpdateNeeded(boolean updateNeeded) {
		if (updateNeeded)
			inCoreFlags |= UPDATE_NEEDED;
		else
			inCoreFlags &= ~UPDATE_NEEDED;
	}

	/**
	 * Get the stage of this entry.
	 * <p>
	 * Entries have one of 4 possible stages: 0-3.
	 *
	 * @return the stage of this entry.
	 */
	public int getStage() {
		return (info[infoOffset + P_FLAGS] >>> 4) & 0x3;
	}

	/**
	 * Returns whether this entry should be skipped from the working tree.
	 *
	 * @return true if this entry should be skipepd.
	 */
	public boolean isSkipWorkTree() {
		return (getExtendedFlags() & SKIP_WORKTREE) != 0;
	}

	/**
	 * Returns whether this entry is intent to be added to the Index.
	 *
	 * @return true if this entry is intent to add.
	 */
	public boolean isIntentToAdd() {
		return (getExtendedFlags() & INTENT_TO_ADD) != 0;
	}

	/**
	 * Returns whether this entry is in the fully-merged stage (0).
	 *
	 * @return true if this entry is merged
	 * @since 2.2
	 */
	public boolean isMerged() {
		return getStage() == STAGE_0;
	}

	/**
	 * Obtain the raw {@link org.eclipse.jgit.lib.FileMode} bits for this entry.
	 *
	 * @return mode bits for the entry.
	 * @see FileMode#fromBits(int)
	 */
	public int getRawMode() {
		return NB.decodeInt32(info, infoOffset + P_MODE);
	}

	/**
	 * Obtain the {@link org.eclipse.jgit.lib.FileMode} for this entry.
	 *
	 * @return the file mode singleton for this entry.
	 */
	public FileMode getFileMode() {
		return FileMode.fromBits(getRawMode());
	}

	/**
	 * Set the file mode for this entry.
	 *
	 * @param mode
	 *            the new mode constant.
	 * @throws java.lang.IllegalArgumentException
	 *             If {@code mode} is
	 *             {@link org.eclipse.jgit.lib.FileMode#MISSING},
	 *             {@link org.eclipse.jgit.lib.FileMode#TREE}, or any other type
	 *             code not permitted in a tree object.
	 */
	public void setFileMode(FileMode mode) {
		switch (mode.getBits() & FileMode.TYPE_MASK) {
		case FileMode.TYPE_MISSING:
		case FileMode.TYPE_TREE:
			throw new IllegalArgumentException(MessageFormat.format(
					JGitText.get().invalidModeForPath, mode, getPathString()));
		}
		NB.encodeInt32(info, infoOffset + P_MODE, mode.getBits());
	}

	void setFileMode(int mode) {
		NB.encodeInt32(info, infoOffset + P_MODE, mode);
	}

	/**
	 * Get the cached creation time of this file, in milliseconds.
	 *
	 * @return cached creation time of this file, in milliseconds since the
	 *         Java epoch (midnight Jan 1, 1970 UTC).
	 */
	public long getCreationTime() {
		return decodeTS(P_CTIME);
	}

	/**
	 * Set the cached creation time of this file, using milliseconds.
	 *
	 * @param when
	 *            new cached creation time of the file, in milliseconds.
	 */
	public void setCreationTime(long when) {
		encodeTS(P_CTIME, when);
	}

	/**
	 * Get the cached last modification date of this file, in milliseconds.
	 * <p>
	 * One of the indicators that the file has been modified by an application
	 * changing the working tree is if the last modification time for the file
	 * differs from the time stored in this entry.
	 *
	 * @return last modification time of this file, in milliseconds since the
	 *         Java epoch (midnight Jan 1, 1970 UTC).
	 * @deprecated use {@link #getLastModifiedInstant()} instead
	 */
	@Deprecated
	public long getLastModified() {
		return decodeTS(P_MTIME);
	}

	/**
	 * Get the cached last modification date of this file.
	 * <p>
	 * One of the indicators that the file has been modified by an application
	 * changing the working tree is if the last modification time for the file
	 * differs from the time stored in this entry.
	 *
	 * @return last modification time of this file.
	 * @since 5.1.9
	 */
	public Instant getLastModifiedInstant() {
		return decodeTSInstant(P_MTIME);
	}

	/**
	 * Set the cached last modification date of this file, using milliseconds.
	 *
	 * @param when
	 *            new cached modification date of the file, in milliseconds.
	 * @deprecated use {@link #setLastModified(Instant)} instead
	 */
	@Deprecated
	public void setLastModified(long when) {
		encodeTS(P_MTIME, when);
	}

	/**
	 * Set the cached last modification date of this file.
	 *
	 * @param when
	 *            new cached modification date of the file.
	 * @since 5.1.9
	 */
	public void setLastModified(Instant when) {
		encodeTS(P_MTIME, when);
	}

	/**
	 * Get the cached size (mod 4 GB) (in bytes) of this file.
	 * <p>
	 * One of the indicators that the file has been modified by an application
	 * changing the working tree is if the size of the file (in bytes) differs
	 * from the size stored in this entry.
	 * <p>
	 * Note that this is the length of the file in the working directory, which
	 * may differ from the size of the decompressed blob if work tree filters
	 * are being used, such as LF&lt;-&gt;CRLF conversion.
	 * <p>
	 * Note also that for very large files, this is the size of the on-disk file
	 * truncated to 32 bits, i.e. modulo 4294967296. If that value is larger
	 * than 2GB, it will appear negative.
	 *
	 * @return cached size of the working directory file, in bytes.
	 */
	public int getLength() {
		return NB.decodeInt32(info, infoOffset + P_SIZE);
	}

	/**
	 * Set the cached size (in bytes) of this file.
	 *
	 * @param sz
	 *            new cached size of the file, as bytes. If the file is larger
	 *            than 2G, cast it to (int) before calling this method.
	 */
	public void setLength(int sz) {
		NB.encodeInt32(info, infoOffset + P_SIZE, sz);
	}

	/**
	 * Set the cached size (in bytes) of this file.
	 *
	 * @param sz
	 *            new cached size of the file, as bytes.
	 */
	public void setLength(long sz) {
		setLength((int) sz);
	}

	/**
	 * Obtain the ObjectId for the entry.
	 * <p>
	 * Using this method to compare ObjectId values between entries is
	 * inefficient as it causes memory allocation.
	 *
	 * @return object identifier for the entry.
	 */
	public ObjectId getObjectId() {
		return ObjectId.fromRaw(idBuffer(), idOffset());
	}

	/**
	 * Set the ObjectId for the entry.
	 *
	 * @param id
	 *            new object identifier for the entry. May be
	 *            {@link org.eclipse.jgit.lib.ObjectId#zeroId()} to remove the
	 *            current identifier.
	 */
	public void setObjectId(AnyObjectId id) {
		id.copyRawTo(idBuffer(), idOffset());
	}

	/**
	 * Set the ObjectId for the entry from the raw binary representation.
	 *
	 * @param bs
	 *            the raw byte buffer to read from. At least 20 bytes after p
	 *            must be available within this byte array.
	 * @param p
	 *            position to read the first byte of data from.
	 */
	public void setObjectIdFromRaw(byte[] bs, int p) {
		final int n = Constants.OBJECT_ID_LENGTH;
		System.arraycopy(bs, p, idBuffer(), idOffset(), n);
	}

	/**
	 * Get the entry's complete path.
	 * <p>
	 * This method is not very efficient and is primarily meant for debugging
	 * and final output generation. Applications should try to avoid calling it,
	 * and if invoked do so only once per interesting entry, where the name is
	 * absolutely required for correct function.
	 *
	 * @return complete path of the entry, from the root of the repository. If
	 *         the entry is in a subtree there will be at least one '/' in the
	 *         returned string.
	 */
	public String getPathString() {
		return toString(path);
	}

	/**
	 * Get a copy of the entry's raw path bytes.
	 *
	 * @return raw path bytes.
	 * @since 3.4
	 */
	public byte[] getRawPath() {
		return path.clone();
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Use for debugging only !
	 */
	@SuppressWarnings("nls")
	@Override
	public String toString() {
		return getFileMode() + " " + getLength() + " "
				+ getLastModifiedInstant()
				+ " " + getObjectId() + " " + getStage() + " "
				+ getPathString() + "\n";
	}

	/**
	 * Copy the ObjectId and other meta fields from an existing entry.
	 * <p>
	 * This method copies everything except the path from one entry to another,
	 * supporting renaming.
	 *
	 * @param src
	 *            the entry to copy ObjectId and meta fields from.
	 */
	public void copyMetaData(DirCacheEntry src) {
		copyMetaData(src, false);
	}

	/**
	 * Copy the ObjectId and other meta fields from an existing entry.
	 * <p>
	 * This method copies everything except the path and possibly stage from one
	 * entry to another, supporting renaming.
	 *
	 * @param src
	 *            the entry to copy ObjectId and meta fields from.
	 * @param keepStage
	 *            if true, the stage attribute will not be copied
	 */
	void copyMetaData(DirCacheEntry src, boolean keepStage) {
		int origflags = NB.decodeUInt16(info, infoOffset + P_FLAGS);
		int newflags = NB.decodeUInt16(src.info, src.infoOffset + P_FLAGS);
		System.arraycopy(src.info, src.infoOffset, info, infoOffset, INFO_LEN);
		final int pLen = origflags & NAME_MASK;
		final int SHIFTED_STAGE_MASK = 0x3 << 12;
		final int pStageShifted;
		if (keepStage)
			pStageShifted = origflags & SHIFTED_STAGE_MASK;
		else
			pStageShifted = newflags & SHIFTED_STAGE_MASK;
		NB.encodeInt16(info, infoOffset + P_FLAGS, pStageShifted | pLen
				| (newflags & ~NAME_MASK & ~SHIFTED_STAGE_MASK));
	}

	/**
	 * @return true if the entry contains extended flags.
	 */
	boolean isExtended() {
		return (info[infoOffset + P_FLAGS] & EXTENDED) != 0;
	}

	private long decodeTS(int pIdx) {
		final int base = infoOffset + pIdx;
		final int sec = NB.decodeInt32(info, base);
		final int ms = NB.decodeInt32(info, base + 4) / 1000000;
		return 1000L * sec + ms;
	}

	private Instant decodeTSInstant(int pIdx) {
		final int base = infoOffset + pIdx;
		final int sec = NB.decodeInt32(info, base);
		final int nano = NB.decodeInt32(info, base + 4);
		return Instant.ofEpochSecond(sec, nano);
	}

	private void encodeTS(int pIdx, long when) {
		final int base = infoOffset + pIdx;
		NB.encodeInt32(info, base, (int) (when / 1000));
		NB.encodeInt32(info, base + 4, ((int) (when % 1000)) * 1000000);
	}

	private void encodeTS(int pIdx, Instant when) {
		final int base = infoOffset + pIdx;
		NB.encodeInt32(info, base, (int) when.getEpochSecond());
		NB.encodeInt32(info, base + 4, when.getNano());
	}

	private int getExtendedFlags() {
		if (isExtended())
			return NB.decodeUInt16(info, infoOffset + P_FLAGS2) << 16;
		else
			return 0;
	}

	private static void checkPath(byte[] path) {
		try {
			SystemReader.getInstance().checkPath(path);
		} catch (CorruptObjectException e) {
			InvalidPathException p = new InvalidPathException(toString(path));
			p.initCause(e);
			throw p;
		}
	}

	static String toString(byte[] path) {
		return UTF_8.decode(ByteBuffer.wrap(path)).toString();
	}

	static int getMaximumInfoLength(boolean extended) {
		return extended ? INFO_LEN_EXTENDED : INFO_LEN;
	}
}
