private RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult WriteObjectOrPack(
            BlobDownloadRequest request,
            int tryCount,
            GitEndPointResponseData response,
            HashSet <string> successfulDownloads = null)
        {
            // To reduce allocations, reuse the same buffer when writing objects in this batch
            byte[] bufToCopyWith = new byte[StreamUtil.DefaultCopyBufferSize];

            string fileName = null;

            switch (response.ContentType)
            {
            case GitObjectContentType.LooseObject:
                string sha = request.ObjectIds.First();
                fileName = this.gitObjects.WriteLooseObject(
                    response.Stream,
                    sha,
                    bufToCopyWith);
                this.AvailableObjects.Add(sha);
                break;

            case GitObjectContentType.PackFile:
                fileName = this.gitObjects.WriteTempPackFile(response);
                this.AvailablePacks.Add(new IndexPackRequest(fileName, request));
                break;

            case GitObjectContentType.BatchedLooseObjects:
                OnLooseObject onLooseObject = (objectStream, sha1) =>
                {
                    this.gitObjects.WriteLooseObject(
                        objectStream,
                        sha1,
                        bufToCopyWith);
                    this.AvailableObjects.Add(sha1);

                    if (successfulDownloads != null)
                    {
                        successfulDownloads.Add(sha1);
                    }

                    // This isn't strictly correct because we don't add object header bytes,
                    // just the actual compressed content length, but we expect the amount of
                    // header data to be negligible compared to the objects themselves.
                    Interlocked.Add(ref this.bytesDownloaded, objectStream.Length);
                };

                new BatchedLooseObjectDeserializer(response.Stream, onLooseObject).ProcessObjects();
                break;
            }

            if (fileName != null)
            {
                // NOTE: If we are writing a file as part of this method, the only case
                // where it's not expected to exist is when running unit tests
                FileInfo info = new FileInfo(fileName);
                if (info.Exists)
                {
                    Interlocked.Add(ref this.bytesDownloaded, info.Length);
                }
                else
                {
                    return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(
                               new GitObjectsHttpRequestor.GitObjectTaskResult(false)));
                }
            }

            return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(
                       new GitObjectsHttpRequestor.GitObjectTaskResult(true)));
        }
 public BatchedLooseObjectDeserializer(Stream source, OnLooseObject onLooseObject)
 {
     this.source        = source;
     this.onLooseObject = onLooseObject;
 }