/// <summary> /// Parse the current pack header /// </summary> private void ReadPackHeader( byte[] buffer, out long timestamp, out long packLength, out long indexLength) { int totalBytes = StreamUtil.TryReadGreedy( this.source, buffer, 0, NumPackHeaderBytes); if (totalBytes == NumPackHeaderBytes) { timestamp = BitConverter.ToInt64(buffer, 0); packLength = BitConverter.ToInt64(buffer, 8); indexLength = BitConverter.ToInt64(buffer, 16); } else { throw new RetryableException( string.Format( "Reached end of stream before expected {0} bytes. Got {1}. Buffer: {2}", NumPackHeaderBytes, totalBytes, SHA1Util.HexStringFromBytes(buffer))); } }
/// <summary> /// Parse the current object header to check if we've reached the end. /// </summary> /// <returns>true if the end of the stream has been reached, false if not</returns> private bool ShouldContinueReading(byte[] curObjectHeader) { int totalBytes = StreamUtil.TryReadGreedy( this.source, curObjectHeader, 0, curObjectHeader.Length); if (totalBytes == NumObjectHeaderBytes) { // Successful header read return(true); } else if (totalBytes == NumObjectIdBytes) { // We may have finished reading all the objects for (int i = 0; i < NumObjectIdBytes; i++) { if (curObjectHeader[i] != 0) { throw new RetryableException( string.Format( "Reached end of stream before we got the expected zero-object ID Buffer: {0}", SHA1Util.HexStringFromBytes(curObjectHeader))); } } return(false); } else { throw new RetryableException( string.Format( "Reached end of stream before expected {0} or {1} bytes. Got {2}. Buffer: {3}", NumObjectHeaderBytes, NumObjectIdBytes, totalBytes, SHA1Util.HexStringFromBytes(curObjectHeader))); } }
/// <summary> /// Read all the objects from the source stream and call <see cref="OnLooseObject"/> for each. /// </summary> /// <returns>The total number of objects read</returns> public int ProcessObjects() { this.ValidateHeader(); // Start reading objects int numObjectsRead = 0; byte[] curObjectHeader = new byte[NumObjectHeaderBytes]; while (true) { bool keepReading = this.ShouldContinueReading(curObjectHeader); if (!keepReading) { break; } // Get the length long curLength = BitConverter.ToInt64(curObjectHeader, NumObjectIdBytes); // Handle the loose object using (Stream rawObjectData = new RestrictedStream(this.source, 0, curLength, leaveOpen: true)) { string objectId = SHA1Util.HexStringFromBytes(curObjectHeader, NumObjectIdBytes); if (objectId.Equals(GVFSConstants.AllZeroSha)) { throw new RetryableException("Received all-zero SHA before end of stream"); } this.onLooseObject(rawObjectData, objectId); numObjectsRead++; } } return(numObjectsRead); }