/// <exception cref="System.IO.IOException"></exception> internal virtual void WriteTo(OutputStream os) { MessageDigest foot = Constants.NewMessageDigest(); DigestOutputStream dos = new DigestOutputStream(os, foot); bool extended = false; for (int i = 0; i < entryCnt; i++) { extended |= sortedEntries[i].IsExtended; } // Write the header. // byte[] tmp = new byte[128]; System.Array.Copy(SIG_DIRC, 0, tmp, 0, SIG_DIRC.Length); NB.EncodeInt32(tmp, 4, extended ? 3 : 2); NB.EncodeInt32(tmp, 8, entryCnt); dos.Write(tmp, 0, 12); // Write the individual file entries. // if (snapshot == null) { // Write a new index, as no entries require smudging. // for (int i_1 = 0; i_1 < entryCnt; i_1++) { sortedEntries[i_1].Write(dos); } } else { int smudge_s = (int)(snapshot.LastModified() / 1000); int smudge_ns = ((int)(snapshot.LastModified() % 1000)) * 1000000; for (int i_1 = 0; i_1 < entryCnt; i_1++) { DirCacheEntry e = sortedEntries[i_1]; if (e.MightBeRacilyClean(smudge_s, smudge_ns)) { e.SmudgeRacilyClean(); } e.Write(dos); } } if (tree != null) { TemporaryBuffer bb = new TemporaryBuffer.LocalFile(); tree.Write(tmp, bb); bb.Close(); NB.EncodeInt32(tmp, 0, EXT_TREE); NB.EncodeInt32(tmp, 4, (int)bb.Length()); dos.Write(tmp, 0, 8); bb.WriteTo(dos, null); } os.Write(foot.Digest()); os.Close(); }
/// <exception cref="System.IO.IOException"></exception> internal virtual void WriteTo(OutputStream os) { MessageDigest foot = Constants.NewMessageDigest(); DigestOutputStream dos = new DigestOutputStream(os, foot); bool extended = false; for (int i = 0; i < entryCnt; i++) { extended |= sortedEntries[i].IsExtended; } // Write the header. // byte[] tmp = new byte[128]; System.Array.Copy(SIG_DIRC, 0, tmp, 0, SIG_DIRC.Length); NB.EncodeInt32(tmp, 4, extended ? 3 : 2); NB.EncodeInt32(tmp, 8, entryCnt); dos.Write(tmp, 0, 12); // Write the individual file entries. int smudge_s; int smudge_ns; if (myLock != null) { // For new files we need to smudge the index entry // if they have been modified "now". Ideally we'd // want the timestamp when we're done writing the index, // so we use the current timestamp as a approximation. myLock.CreateCommitSnapshot(); snapshot = myLock.GetCommitSnapshot(); smudge_s = (int)(snapshot.LastModified() / 1000); smudge_ns = ((int)(snapshot.LastModified() % 1000)) * 1000000; } else { // Used in unit tests only smudge_ns = 0; smudge_s = 0; } // Check if tree is non-null here since calling updateSmudgedEntries // will automatically build it via creating a DirCacheIterator bool writeTree = tree != null; if (repository != null && entryCnt > 0) { UpdateSmudgedEntries(); } for (int i_1 = 0; i_1 < entryCnt; i_1++) { DirCacheEntry e = sortedEntries[i_1]; if (e.MightBeRacilyClean(smudge_s, smudge_ns)) { e.SmudgeRacilyClean(); } e.Write(dos); } if (writeTree) { TemporaryBuffer bb = new TemporaryBuffer.LocalFile(); tree.Write(tmp, bb); bb.Close(); NB.EncodeInt32(tmp, 0, EXT_TREE); NB.EncodeInt32(tmp, 4, (int)bb.Length()); dos.Write(tmp, 0, 8); bb.WriteTo(dos, null); } writeIndexChecksum = foot.Digest(); os.Write(writeIndexChecksum); os.Close(); }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="NGit.Errors.CorruptObjectException"></exception> private void ReadFrom(InputStream inStream) { BufferedInputStream @in = new BufferedInputStream(inStream); MessageDigest md = Constants.NewMessageDigest(); // Read the index header and verify we understand it. // byte[] hdr = new byte[20]; IOUtil.ReadFully(@in, hdr, 0, 12); md.Update(hdr, 0, 12); if (!Is_DIRC(hdr)) { throw new CorruptObjectException(JGitText.Get().notADIRCFile); } int ver = NB.DecodeInt32(hdr, 4); bool extended = false; if (ver == 3) { extended = true; } else { if (ver != 2) { throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().unknownDIRCVersion , Sharpen.Extensions.ValueOf(ver))); } } entryCnt = NB.DecodeInt32(hdr, 8); if (entryCnt < 0) { throw new CorruptObjectException(JGitText.Get().DIRCHasTooManyEntries); } snapshot = FileSnapshot.Save(liveFile); int smudge_s = (int)(snapshot.LastModified() / 1000); int smudge_ns = ((int)(snapshot.LastModified() % 1000)) * 1000000; // Load the individual file entries. // int infoLength = DirCacheEntry.GetMaximumInfoLength(extended); byte[] infos = new byte[infoLength * entryCnt]; sortedEntries = new DirCacheEntry[entryCnt]; MutableInteger infoAt = new MutableInteger(); for (int i = 0; i < entryCnt; i++) { sortedEntries[i] = new DirCacheEntry(infos, infoAt, @in, md, smudge_s, smudge_ns); } // After the file entries are index extensions, and then a footer. // for (; ;) { @in.Mark(21); IOUtil.ReadFully(@in, hdr, 0, 20); if (@in.Read() < 0) { // No extensions present; the file ended where we expected. // break; } @in.Reset(); md.Update(hdr, 0, 8); IOUtil.SkipFully(@in, 8); long sz = NB.DecodeUInt32(hdr, 4); switch (NB.DecodeInt32(hdr, 0)) { case EXT_TREE: { if (int.MaxValue < sz) { throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().DIRCExtensionIsTooLargeAt , FormatExtensionName(hdr), Sharpen.Extensions.ValueOf(sz))); } byte[] raw = new byte[(int)sz]; IOUtil.ReadFully(@in, raw, 0, raw.Length); md.Update(raw, 0, raw.Length); tree = new DirCacheTree(raw, new MutableInteger(), null); break; } default: { if (hdr[0] >= 'A' && ((sbyte)hdr[0]) <= 'Z') { // The extension is optional and is here only as // a performance optimization. Since we do not // understand it, we can safely skip past it, after // we include its data in our checksum. // SkipOptionalExtension(@in, md, hdr, sz); } else { // The extension is not an optimization and is // _required_ to understand this index format. // Since we did not trap it above we must abort. // throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().DIRCExtensionNotSupportedByThisVersion , FormatExtensionName(hdr))); } break; } } } readIndexChecksum = md.Digest(); if (!Arrays.Equals(readIndexChecksum, hdr)) { throw new CorruptObjectException(JGitText.Get().DIRCChecksumMismatch); } }