/// <summary> /// Uses a <see cref="PrefetchPacksDeserializer"/> to read the packs from the stream. /// </summary> private RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult DeserializePrefetchPacks( HttpGitObjects.GitEndPointResponseData response, ref long latestTimestamp) { using (ITracer activity = this.Tracer.StartActivity(nameof(this.DeserializePrefetchPacks), EventLevel.Informational)) { PrefetchPacksDeserializer deserializer = new PrefetchPacksDeserializer(response.Stream); foreach (PrefetchPacksDeserializer.PackAndIndex pack in deserializer.EnumeratePacks()) { string packName = string.Format("{0}-{1}-{2}.pack", GVFSConstants.PrefetchPackPrefix, pack.Timestamp, pack.UniqueId); string packFullPath = Path.Combine(this.Enlistment.GitPackRoot, packName); string idxName = string.Format("{0}-{1}-{2}.idx", GVFSConstants.PrefetchPackPrefix, pack.Timestamp, pack.UniqueId); string idxFullPath = Path.Combine(this.Enlistment.GitPackRoot, idxName); EventMetadata data = new EventMetadata(); data["timestamp"] = pack.Timestamp.ToString(); data["uniqueId"] = pack.UniqueId; activity.RelatedEvent(EventLevel.Informational, "Receiving Pack/Index", data); // Write the pack // If it fails, TryWriteNamedPackOrIdx cleans up the packfile and we retry the prefetch if (!this.TryWriteNamedPackOrIdx(activity, pack.PackStream, packFullPath)) { return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult(null, true)); } // We will try to build an index if the server does not send one if (pack.IndexStream == null) { if (!this.TryBuildIndex(activity, pack, packFullPath)) { return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult(null, true)); } } else if (!this.TryWriteNamedPackOrIdx(activity, pack.IndexStream, idxFullPath)) { // Try to build the index manually, then retry the prefetch if (this.TryBuildIndex(activity, pack, packFullPath)) { // If we were able to recreate the failed index // we can start the prefetch at the next timestamp latestTimestamp = pack.Timestamp; } // The download stream will not be in a good state if the index download fails. // So we have to restart the prefetch return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult(null, true)); } latestTimestamp = pack.Timestamp; } return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult( new HttpGitObjects.GitObjectTaskResult(true))); } }
public virtual string WriteTempPackFile(HttpGitObjects.GitEndPointResponseData response) { string fileName = Path.GetRandomFileName(); string fullPath = Path.Combine(this.Enlistment.GitPackRoot, fileName); this.TryWriteNamedPackOrIdx( tracer: null, source: response.Stream, targetFullPath: fullPath, throwOnError: true); return(fullPath); }
private RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult TrySavePackOrLooseObject(IEnumerable <string> objectShas, bool unpackObjects, HttpGitObjects.GitEndPointResponseData responseData) { if (responseData.ContentType == HttpGitObjects.ContentType.LooseObject) { List <string> objectShaList = objectShas.Distinct().ToList(); if (objectShaList.Count != 1) { return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult(new InvalidOperationException("Received loose object when multiple objects were requested."), shouldRetry : false)); } this.WriteLooseObject(this.Enlistment.WorkingDirectoryRoot, responseData.Stream, objectShaList[0]); } else if (responseData.ContentType == HttpGitObjects.ContentType.BatchedLooseObjects) { BatchedLooseObjectDeserializer deserializer = new BatchedLooseObjectDeserializer( responseData.Stream, (stream, sha) => this.WriteLooseObject(this.Enlistment.WorkingDirectoryRoot, stream, sha)); deserializer.ProcessObjects(); } else { GitProcess.Result result = this.TryAddPackFile(responseData.Stream, unpackObjects); if (result.HasErrors) { return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult(new InvalidOperationException("Could not add pack file: " + result.Errors), shouldRetry : false)); } } return(new RetryWrapper <HttpGitObjects.GitObjectTaskResult> .CallbackResult(new HttpGitObjects.GitObjectTaskResult(true))); }