@@ -72,85 +72,99 @@ public override void Prefetch(string branchOrCommit, bool isBranch)
7272 commitToFetch = branchOrCommit ;
7373 }
7474
75- this . DownloadMissingCommit ( commitToFetch , this . GitObjects ) ;
76-
77- // Configure pipeline
78- // Checkout uses DiffHelper when running checkout.Start(), which we use instead of LsTreeHelper
79- // Checkout diff output => FindBlobs => BatchDownload => IndexPack => Checkout available blobs
80- CheckoutStage checkout = new CheckoutStage ( this . checkoutThreadCount , this . FolderList , commitToFetch , this . Tracer , this . Enlistment , this . forceCheckout ) ;
81- FindBlobsStage blobFinder = new FindBlobsStage ( this . SearchThreadCount , checkout . RequiredBlobs , checkout . AvailableBlobShas , this . Tracer , this . Enlistment ) ;
82- BatchObjectDownloadStage downloader = new BatchObjectDownloadStage ( this . DownloadThreadCount , this . ChunkSize , blobFinder . MissingBlobs , checkout . AvailableBlobShas , this . Tracer , this . Enlistment , this . ObjectRequestor , this . GitObjects ) ;
83- IndexPackStage packIndexer = new IndexPackStage ( this . IndexThreadCount , downloader . AvailablePacks , checkout . AvailableBlobShas , this . Tracer , this . GitObjects ) ;
75+ using ( new IndexLock ( this . Enlistment . EnlistmentRoot , this . Tracer ) )
76+ {
77+ this . DownloadMissingCommit ( commitToFetch , this . GitObjects ) ;
8478
85- // Start pipeline
86- downloader . Start ( ) ;
87- blobFinder . Start ( ) ;
88- checkout . Start ( ) ;
79+ // Configure pipeline
80+ // Checkout uses DiffHelper when running checkout.Start(), which we use instead of LsTreeHelper
81+ // Checkout diff output => FindBlobs => BatchDownload => IndexPack => Checkout available blobs
82+ CheckoutStage checkout = new CheckoutStage ( this . checkoutThreadCount , this . FolderList , commitToFetch , this . Tracer , this . Enlistment , this . forceCheckout ) ;
83+ FindBlobsStage blobFinder = new FindBlobsStage ( this . SearchThreadCount , checkout . RequiredBlobs , checkout . AvailableBlobShas , this . Tracer , this . Enlistment ) ;
84+ BatchObjectDownloadStage downloader = new BatchObjectDownloadStage ( this . DownloadThreadCount , this . ChunkSize , blobFinder . MissingBlobs , checkout . AvailableBlobShas , this . Tracer , this . Enlistment , this . ObjectRequestor , this . GitObjects ) ;
85+ IndexPackStage packIndexer = new IndexPackStage ( this . IndexThreadCount , downloader . AvailablePacks , checkout . AvailableBlobShas , this . Tracer , this . GitObjects ) ;
8986
90- blobFinder . WaitForCompletion ( ) ;
91- this . HasFailures |= blobFinder . HasFailures ;
87+ // Start pipeline
88+ downloader . Start ( ) ;
89+ blobFinder . Start ( ) ;
90+ checkout . Start ( ) ;
9291
93- // Delay indexing. It interferes with FindMissingBlobs, and doesn't help Bootstrapping.
94- packIndexer . Start ( ) ;
92+ blobFinder . WaitForCompletion ( ) ;
93+ this . HasFailures |= blobFinder . HasFailures ;
9594
96- downloader . WaitForCompletion ( ) ;
97- this . HasFailures |= downloader . HasFailures ;
95+ // Delay indexing. It interferes with FindMissingBlobs, and doesn't help Bootstrapping.
96+ packIndexer . Start ( ) ;
9897
99- packIndexer . WaitForCompletion ( ) ;
100- this . HasFailures |= packIndexer . HasFailures ;
98+ downloader . WaitForCompletion ( ) ;
99+ this . HasFailures |= downloader . HasFailures ;
101100
102- // Since pack indexer is the last to finish before checkout finishes, it should propagate completion.
103- // This prevents availableObjects from completing before packIndexer can push its objects through this link.
104- checkout . AvailableBlobShas . CompleteAdding ( ) ;
105- checkout . WaitForCompletion ( ) ;
106- this . HasFailures |= checkout . HasFailures ;
101+ packIndexer . WaitForCompletion ( ) ;
102+ this . HasFailures |= packIndexer . HasFailures ;
107103
108- if ( ! this . SkipConfigUpdate && ! this . HasFailures )
109- {
110- this . UpdateRefs ( branchOrCommit , isBranch , refs ) ;
104+ // Since pack indexer is the last to finish before checkout finishes, it should propagate completion.
105+ // This prevents availableObjects from completing before packIndexer can push its objects through this link.
106+ checkout . AvailableBlobShas . CompleteAdding ( ) ;
107+ checkout . WaitForCompletion ( ) ;
108+ this . HasFailures |= checkout . HasFailures ;
111109
112- if ( isBranch )
110+ if ( ! this . SkipConfigUpdate && ! this . HasFailures )
113111 {
114- // Update the refspec before setting the upstream or git will complain the remote branch doesn't exist
115- this . HasFailures |= ! this . UpdateRefSpec ( this . Tracer , this . Enlistment , branchOrCommit , refs ) ;
112+ bool shouldSignIndex = ! this . GetIsIndexSigningOff ( ) ;
116113
117- using ( ITracer activity = this . Tracer . StartActivity ( "SetUpstream" , EventLevel . Informational ) )
114+ // Update the index - note that this will take some time
115+ EventMetadata updateIndexMetadata = new EventMetadata ( ) ;
116+ updateIndexMetadata . Add ( "IndexSigningIsOff" , shouldSignIndex ) ;
117+ using ( ITracer activity = this . Tracer . StartActivity ( "UpdateIndex" , EventLevel . Informational , Keywords . Telemetry , updateIndexMetadata ) )
118118 {
119- string remoteBranch = refs . GetBranchRefPairs ( ) . Single ( ) . Key ;
120- GitProcess git = new GitProcess ( this . Enlistment ) ;
121- GitProcess . Result result = git . SetUpstream ( branchOrCommit , remoteBranch ) ;
122- if ( result . ExitCodeIsFailure )
119+ Index sourceIndex = this . GetSourceIndex ( ) ;
120+ GitIndexGenerator indexGen = new GitIndexGenerator ( this . Tracer , this . Enlistment , shouldSignIndex ) ;
121+ indexGen . CreateFromRef ( commitToFetch , indexVersion : 2 , isFinal : false ) ;
122+ this . HasFailures |= indexGen . HasFailures ;
123+
124+ if ( ! indexGen . HasFailures )
123125 {
124- activity . RelatedError ( "Could not set upstream for {0} to {1}: {2}" , branchOrCommit , remoteBranch , result . Errors ) ;
125- this . HasFailures = true ;
126+ Index newIndex = new Index (
127+ this . Enlistment . EnlistmentRoot ,
128+ this . Tracer ,
129+ indexGen . TemporaryIndexFilePath ,
130+ readOnly : false ) ;
131+
132+ // Update from disk only if the caller says it is ok via command line
133+ // or if we updated the whole tree and know that all files are up to date
134+ bool allowIndexMetadataUpdateFromWorkingTree = this . allowIndexMetadataUpdateFromWorkingTree || checkout . UpdatedWholeTree ;
135+ newIndex . UpdateFileSizesAndTimes ( checkout . AddedOrEditedLocalFiles , allowIndexMetadataUpdateFromWorkingTree , shouldSignIndex , sourceIndex ) ;
136+
137+ // All the slow stuff is over, so we will now move the final index into .git\index, shortly followed by
138+ // updating the ref files and releasing index.lock.
139+ string indexPath = Path . Combine ( this . Enlistment . DotGitRoot , GVFSConstants . DotGit . IndexName ) ;
140+ this . Tracer . RelatedEvent ( EventLevel . Informational , "MoveUpdatedIndexToFinalLocation" , new EventMetadata ( ) { { "UpdatedIndex" , indexGen . TemporaryIndexFilePath } , { "Index" , indexPath } } ) ;
141+ File . Delete ( indexPath ) ;
142+ File . Move ( indexGen . TemporaryIndexFilePath , indexPath ) ;
143+ newIndex . WriteFastFetchIndexVersionMarker ( ) ;
126144 }
127145 }
128- }
129-
130- bool shouldSignIndex = ! this . GetIsIndexSigningOff ( ) ;
131146
132- // Update the index
133- EventMetadata updateIndexMetadata = new EventMetadata ( ) ;
134- updateIndexMetadata . Add ( "IndexSigningIsOff" , shouldSignIndex ) ;
135- using ( ITracer activity = this . Tracer . StartActivity ( "UpdateIndex" , EventLevel . Informational , Keywords . Telemetry , updateIndexMetadata ) )
136- {
137- Index sourceIndex = this . GetSourceIndex ( ) ;
138- GitIndexGenerator indexGen = new GitIndexGenerator ( this . Tracer , this . Enlistment , shouldSignIndex ) ;
139- indexGen . CreateFromHeadTree ( indexVersion : 2 ) ;
140- this . HasFailures |= indexGen . HasFailures ;
141-
142- if ( ! indexGen . HasFailures )
147+ if ( ! this . HasFailures )
143148 {
144- Index newIndex = new Index (
145- this . Enlistment . EnlistmentRoot ,
146- this . Tracer ,
147- Path . Combine ( this . Enlistment . DotGitRoot , GVFSConstants . DotGit . IndexName ) ,
148- readOnly : false ) ;
149-
150- // Update from disk only if the caller says it is ok via command line
151- // or if we updated the whole tree and know that all files are up to date
152- bool allowIndexMetadataUpdateFromWorkingTree = this . allowIndexMetadataUpdateFromWorkingTree || checkout . UpdatedWholeTree ;
153- newIndex . UpdateFileSizesAndTimes ( checkout . AddedOrEditedLocalFiles , allowIndexMetadataUpdateFromWorkingTree , shouldSignIndex , sourceIndex ) ;
149+ this . UpdateRefs ( branchOrCommit , isBranch , refs ) ;
150+
151+ if ( isBranch )
152+ {
153+ // Update the refspec before setting the upstream or git will complain the remote branch doesn't exist
154+ this . HasFailures |= ! this . UpdateRefSpec ( this . Tracer , this . Enlistment , branchOrCommit , refs ) ;
155+
156+ using ( ITracer activity = this . Tracer . StartActivity ( "SetUpstream" , EventLevel . Informational ) )
157+ {
158+ string remoteBranch = refs . GetBranchRefPairs ( ) . Single ( ) . Key ;
159+ GitProcess git = new GitProcess ( this . Enlistment ) ;
160+ GitProcess . Result result = git . SetUpstream ( branchOrCommit , remoteBranch ) ;
161+ if ( result . ExitCodeIsFailure )
162+ {
163+ activity . RelatedError ( "Could not set upstream for {0} to {1}: {2}" , branchOrCommit , remoteBranch , result . Errors ) ;
164+ this . HasFailures = true ;
165+ }
166+ }
167+ }
154168 }
155169 }
156170 }
@@ -183,18 +197,10 @@ protected override void UpdateRefs(string branchOrCommit, bool isBranch, GitRefs
183197 private Index GetSourceIndex ( )
184198 {
185199 string indexPath = Path . Combine ( this . Enlistment . DotGitRoot , GVFSConstants . DotGit . IndexName ) ;
186- string backupIndexPath = Path . Combine ( this . Enlistment . DotGitRoot , GVFSConstants . DotGit . IndexName + ".backup" ) ;
187200
188201 if ( File . Exists ( indexPath ) )
189202 {
190- // Note that this moves the current index, leaving nothing behind
191- // This is intentional as we only need it for the purpose of updating the
192- // new index and leaving it behind can make updating slower.
193- this . Tracer . RelatedEvent ( EventLevel . Informational , "CreateBackup" , new EventMetadata ( ) { { "BackupIndexName" , backupIndexPath } } ) ;
194- File . Delete ( backupIndexPath ) ;
195- File . Move ( indexPath , backupIndexPath ) ;
196-
197- Index output = new Index ( this . Enlistment . EnlistmentRoot , this . Tracer , backupIndexPath , readOnly : true ) ;
203+ Index output = new Index ( this . Enlistment . EnlistmentRoot , this . Tracer , indexPath , readOnly : true ) ;
198204 output . Parse ( ) ;
199205 return output ;
200206 }
0 commit comments