/// <summary>Invoked for commits, trees, tags, and small blobs.</summary> /// <remarks>Invoked for commits, trees, tags, and small blobs.</remarks> /// <param name="obj">the object info, populated.</param> /// <param name="typeCode">the type of the object.</param> /// <param name="data">inflated data for the object.</param> /// <exception cref="System.IO.IOException">the object cannot be archived.</exception> protected internal abstract void OnInflatedObjectData(PackedObjectInfo obj, int typeCode , byte[] data);
/// <summary>Provide the implementation with a base that was outside of the pack.</summary> /// <remarks> /// Provide the implementation with a base that was outside of the pack. /// <p> /// This event only occurs on a thin pack for base objects that were outside /// of the pack and came from the local repository. Usually an implementation /// uses this event to compress the base and append it onto the end of the /// pack, so the pack stays self-contained. /// </remarks> /// <param name="typeCode">type of the base object.</param> /// <param name="data">complete content of the base object.</param> /// <param name="info"> /// packed object information for this base. Implementors must /// populate the CRC and offset members if returning true. /// </param> /// <returns> /// true if the /// <code>info</code> /// should be included in the object list /// returned by /// <see cref="GetSortedObjectList(System.Collections.Generic.IComparer{T})">GetSortedObjectList(System.Collections.Generic.IComparer<T>) /// </see> /// , false if it /// should not be included. /// </returns> /// <exception cref="System.IO.IOException">the base could not be included into the pack. /// </exception> protected internal abstract bool OnAppendBase(int typeCode, byte[] data, PackedObjectInfo info);
/// <exception cref="System.IO.IOException"></exception> private PackParser.ObjectTypeAndSize OpenDatabase(PackedObjectInfo obj, PackParser.ObjectTypeAndSize info) { bOffset = 0; bAvail = 0; return SeekDatabase(obj, info); }
/// <summary>Construct a PackedObjectInfo instance for this parser.</summary> /// <remarks>Construct a PackedObjectInfo instance for this parser.</remarks> /// <param name="id">identity of the object to be tracked.</param> /// <param name="delta"> /// if the object was previously an unresolved delta, this is the /// delta object that was tracking it. Otherwise null. /// </param> /// <param name="deltaBase"> /// if the object was previously an unresolved delta, this is the /// ObjectId of the base of the delta. The base may be outside of /// the pack stream if the stream was a thin-pack. /// </param> /// <returns>info object containing this object's data.</returns> protected internal virtual PackedObjectInfo NewInfo(AnyObjectId id, PackParser.UnresolvedDelta delta, ObjectId deltaBase) { PackedObjectInfo oe = new PackedObjectInfo(id); if (delta != null) { oe.SetCRC(delta.crc); } return oe; }
private PackParser.UnresolvedDelta FirstChildOf(PackedObjectInfo oe) { PackParser.UnresolvedDelta a = Reverse(RemoveBaseById(oe)); PackParser.UnresolvedDelta b = Reverse(baseByPos.Remove(oe.GetOffset())); if (a == null) { return b; } if (b == null) { return a; } PackParser.UnresolvedDelta first = null; PackParser.UnresolvedDelta last = null; while (a != null || b != null) { PackParser.UnresolvedDelta curr; if (b == null || (a != null && a.position < b.position)) { curr = a; a = a.next; } else { curr = b; b = b.next; } if (last != null) { last.next = curr; } else { first = curr; } last = curr; curr.next = null; } return first; }
/// <exception cref="System.IO.IOException"></exception> private void ResolveDeltas(long pos, int oldCRC, int type, byte[] data, PackedObjectInfo oe) { crc.Reset(); Position(pos); int c = ReadFrom(IndexPack.Source.FILE); int typeCode = (c >> 4) & 7; long sz = c & 15; int shift = 4; while ((c & unchecked((int)(0x80))) != 0) { c = ReadFrom(IndexPack.Source.FILE); sz += (c & unchecked((int)(0x7f))) << shift; shift += 7; } switch (typeCode) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: { type = typeCode; data = InflateAndReturn(IndexPack.Source.FILE, sz); break; } case Constants.OBJ_OFS_DELTA: { c = ReadFrom(IndexPack.Source.FILE) & unchecked((int)(0xff)); while ((c & 128) != 0) { c = ReadFrom(IndexPack.Source.FILE) & unchecked((int)(0xff)); } data = BinaryDelta.Apply(data, InflateAndReturn(IndexPack.Source.FILE, sz)); break; } case Constants.OBJ_REF_DELTA: { crc.Update(buf, Fill(IndexPack.Source.FILE, 20), 20); Use(20); data = BinaryDelta.Apply(data, InflateAndReturn(IndexPack.Source.FILE, sz)); break; } default: { throw new IOException(MessageFormat.Format(JGitText.Get().unknownObjectType, typeCode )); } } int crc32 = (int)crc.GetValue(); if (oldCRC != crc32) { throw new IOException(MessageFormat.Format(JGitText.Get().corruptionDetectedReReadingAt , pos)); } if (oe == null) { objectDigest.Update(Constants.EncodedTypeString(type)); objectDigest.Update(unchecked((byte)' ')); objectDigest.Update(Constants.EncodeASCII(data.Length)); objectDigest.Update(unchecked((byte)0)); objectDigest.Update(data); tempObjectId.FromRaw(objectDigest.Digest(), 0); VerifySafeObject(tempObjectId, type, data); oe = new PackedObjectInfo(pos, crc32, tempObjectId); AddObjectAndTrack(oe); } ResolveChildDeltas(pos, type, data, oe); }
/// <exception cref="System.IO.IOException"></exception> protected internal override void OnInflatedObjectData(PackedObjectInfo obj, int typeCode , byte[] data) { }
private void AddObjectAndTrack(PackedObjectInfo oe) { entries[entryCount++] = oe; if (NeedNewObjectIds()) { newObjectIds.Add(oe); } }
/// <exception cref="System.IO.IOException"></exception> private void Whole(int type, long pos, long sz) { objectDigest.Update(Constants.EncodedTypeString(type)); objectDigest.Update(unchecked((byte)' ')); objectDigest.Update(Constants.EncodeASCII(sz)); objectDigest.Update(unchecked((byte)0)); bool checkContentLater = false; if (type == Constants.OBJ_BLOB) { InputStream inf = Inflate(IndexPack.Source.INPUT, sz); long cnt = 0; while (cnt < sz) { int r = inf.Read(readBuffer); if (r <= 0) { break; } objectDigest.Update(readBuffer, 0, r); cnt += r; } inf.Close(); tempObjectId.FromRaw(objectDigest.Digest(), 0); checkContentLater = readCurs.Has(tempObjectId); } else { byte[] data = InflateAndReturn(IndexPack.Source.INPUT, sz); objectDigest.Update(data); tempObjectId.FromRaw(objectDigest.Digest(), 0); VerifySafeObject(tempObjectId, type, data); } int crc32 = (int)crc.GetValue(); PackedObjectInfo obj = new PackedObjectInfo(pos, crc32, tempObjectId); AddObjectAndTrack(obj); if (checkContentLater) { deferredCheckBlobs.AddItem(obj); } }
/// <exception cref="System.IO.IOException"></exception> protected internal override void OnEndWholeObject(PackedObjectInfo info) { info.SetCRC((int)crc.GetValue()); }
private void GrowEntries() { PackedObjectInfo[] ne; ne = new PackedObjectInfo[(int)objectCount + baseById.Size()]; System.Array.Copy(entries, 0, ne, 0, entryCount); entries = ne; }
/// <exception cref="System.IO.IOException"></exception> private void FixThinPack(ProgressMonitor progress) { GrowEntries(); if (needBaseObjectIds) { baseObjectIds = new ObjectIdSubclassMap<ObjectId>(); } packDigest.Reset(); originalEOF = packOut.Length() - 20; Deflater def = new Deflater(Deflater.DEFAULT_COMPRESSION, false); IList<IndexPack.DeltaChain> missing = new AList<IndexPack.DeltaChain>(64); long end = originalEOF; foreach (IndexPack.DeltaChain baseId in baseById) { if (baseId.head == null) { continue; } if (needBaseObjectIds) { baseObjectIds.Add(baseId); } ObjectLoader ldr; try { ldr = readCurs.Open(baseId); } catch (MissingObjectException) { missing.AddItem(baseId); continue; } byte[] data = ldr.GetCachedBytes(int.MaxValue); int typeCode = ldr.GetType(); PackedObjectInfo oe; crc.Reset(); packOut.Seek(end); WriteWhole(def, typeCode, data); oe = new PackedObjectInfo(end, (int)crc.GetValue(), baseId); entries[entryCount++] = oe; end = packOut.GetFilePointer(); ResolveChildDeltas(oe.GetOffset(), typeCode, data, oe); if (progress.IsCancelled()) { throw new IOException(JGitText.Get().downloadCancelledDuringIndexing); } } def.Finish(); foreach (IndexPack.DeltaChain @base in missing) { if (@base.head != null) { throw new MissingObjectException(@base, "delta base"); } } if (end - originalEOF < 20) { // Ugly corner case; if what we appended on to complete deltas // doesn't completely cover the SHA-1 we have to truncate off // we need to shorten the file, otherwise we will include part // of the old footer as object content. packOut.SetLength(end); } FixHeaderFooter(packcsum, packDigest.Digest()); }
/// <exception cref="System.IO.IOException"></exception> private void ResolveChildDeltas(long pos, int type, byte[] data, PackedObjectInfo oe) { IndexPack.UnresolvedDelta a = Reverse(RemoveBaseById(oe)); IndexPack.UnresolvedDelta b = Reverse(baseByPos.Remove(pos)); while (a != null && b != null) { if (a.position < b.position) { ResolveDeltas(a.position, a.crc, type, data, null); a = a.next; } else { ResolveDeltas(b.position, b.crc, type, data, null); b = b.next; } } ResolveChildDeltaChain(type, data, a); ResolveChildDeltaChain(type, data, b); }
/// <summary>Reposition the database to re-read a previously stored object.</summary> /// <remarks> /// Reposition the database to re-read a previously stored object. /// <p> /// If the database is computing CRC-32 checksums for object data, it should /// reset its internal CRC instance during this method call. /// </remarks> /// <param name="obj"> /// the object position to begin reading from. This is from /// <see cref="NewInfo(NGit.AnyObjectId, UnresolvedDelta, NGit.ObjectId)">NewInfo(NGit.AnyObjectId, UnresolvedDelta, NGit.ObjectId) /// </see> /// . /// </param> /// <param name="info">object to populate with type and size.</param> /// <returns> /// the /// <code>info</code> /// object. /// </returns> /// <exception cref="System.IO.IOException">the database cannot reposition to this location. /// </exception> protected internal abstract PackParser.ObjectTypeAndSize SeekDatabase(PackedObjectInfo obj, PackParser.ObjectTypeAndSize info);
/// <exception cref="System.IO.IOException"></exception> protected internal override PackParser.ObjectTypeAndSize SeekDatabase(PackedObjectInfo obj, PackParser.ObjectTypeAndSize info) { @out.Seek(obj.GetOffset()); crc.Reset(); return ReadObjectHeader(info); }
/// <summary>Event notifying the the current object.</summary> /// <remarks>Event notifying the the current object.</remarks> /// <param name="info">object information.</param> /// <exception cref="System.IO.IOException">the object cannot be recorded.</exception> protected internal abstract void OnEndWholeObject(PackedObjectInfo info);
/// <exception cref="System.IO.IOException"></exception> protected internal override bool OnAppendBase(int typeCode, byte[] data, PackedObjectInfo info) { info.SetOffset(packEnd); byte[] buf = Buffer(); int sz = data.Length; int len = 0; buf[len++] = unchecked((byte)((typeCode << 4) | sz & 15)); sz = (int)(((uint)sz) >> 4); while (sz > 0) { buf[len - 1] |= unchecked((int)(0x80)); buf[len++] = unchecked((byte)(sz & unchecked((int)(0x7f)))); sz = (int)(((uint)sz) >> 7); } tailDigest.Update(buf, 0, len); crc.Reset(); crc.Update(buf, 0, len); @out.Seek(packEnd); @out.Write(buf, 0, len); packEnd += len; if (def == null) { def = new Deflater(Deflater.DEFAULT_COMPRESSION, false); } else { def.Reset(); } def.SetInput(data); def.Finish(); while (!def.IsFinished) { len = def.Deflate(buf); tailDigest.Update(buf, 0, len); crc.Update(buf, 0, len); @out.Write(buf, 0, len); packEnd += len; } info.SetCRC((int)crc.GetValue()); return true; }
/// <exception cref="System.IO.IOException"></exception> private void ResolveDeltas(PackedObjectInfo oe, ProgressMonitor progress) { PackParser.UnresolvedDelta children = FirstChildOf(oe); if (children == null) { return; } PackParser.DeltaVisit visit = new PackParser.DeltaVisit(); visit.nextChild = children; PackParser.ObjectTypeAndSize info = OpenDatabase(oe, new PackParser.ObjectTypeAndSize ()); switch (info.type) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: { visit.data = InflateAndReturn(PackParser.Source.DATABASE, info.size); visit.id = oe; break; } default: { throw new IOException(MessageFormat.Format(JGitText.Get().unknownObjectType, Sharpen.Extensions.ValueOf (info.type))); } } if (!CheckCRC(oe.GetCRC())) { throw new IOException(MessageFormat.Format(JGitText.Get().corruptionDetectedReReadingAt , Sharpen.Extensions.ValueOf(oe.GetOffset()))); } ResolveDeltas(visit.Next(), info.type, info, progress); }
internal static bool CanStore(PackedObjectInfo oe) { // We are limited to 4 GB per pack as offset is 32 bit unsigned int. // return (long)(((ulong)oe.GetOffset()) >> 1) < int.MaxValue; }
private void GrowEntries(int extraObjects) { PackedObjectInfo[] ne; ne = new PackedObjectInfo[(int)objectCount + extraObjects]; System.Array.Copy(entries, 0, ne, 0, entryCount); entries = ne; }
/// <exception cref="System.IO.IOException"></exception> private void ResolveDeltas(PackedObjectInfo oe) { int oldCRC = oe.GetCRC(); if (baseById.Get(oe) != null || baseByPos.ContainsKey(oe.GetOffset())) { ResolveDeltas(oe.GetOffset(), oldCRC, Constants.OBJ_BAD, null, oe); } }