@@ -296,62 +296,65 @@ func TestRepository_NeedsFetch(t *testing.T) {
296296 assert .False (t , repo .NeedsFetch (15 * time .Minute ))
297297}
298298
299- func TestRepository_FetchVerifiedDoesNotCoalesce (t * testing.T ) {
300- ctx := context .Background ()
301- tmpDir := t .TempDir ()
302- upstreamPath := createBareRepo (t , tmpDir )
303-
304- clonePath := filepath .Join (tmpDir , "clone" )
305- repo := & Repository {
306- state : StateEmpty ,
307- config : testRepoConfig (),
308- path : clonePath ,
309- upstreamURL : upstreamPath ,
310- fetchSem : make (chan struct {}, 1 ),
311- }
312- repo .fetchSem <- struct {}{}
313- assert .NoError (t , repo .Clone (ctx ))
299+ func TestRepository_FetchDoesNotCoalesceWithExclusion (t * testing.T ) {
300+ for _ , verified := range []bool {false , true } {
301+ t .Run (fmt .Sprintf ("verified=%t" , verified ), func (t * testing.T ) {
302+ ctx := context .Background ()
303+ tmpDir := t .TempDir ()
304+ upstreamPath := createBareRepo (t , tmpDir )
305+
306+ clonePath := filepath .Join (tmpDir , "clone" )
307+ repo := & Repository {
308+ state : StateEmpty ,
309+ config : testRepoConfig (),
310+ path : clonePath ,
311+ upstreamURL : upstreamPath ,
312+ fetchSem : make (chan struct {}, 1 ),
313+ }
314+ repo .fetchSem <- struct {}{}
315+ assert .NoError (t , repo .Clone (ctx ))
316+
317+ workPath := filepath .Join (tmpDir , "work" )
318+ assert .NoError (t , os .WriteFile (filepath .Join (workPath , "f.txt" ), []byte ("y" ), 0o644 ))
319+ for _ , args := range [][]string {
320+ {"git" , "-C" , workPath , "commit" , "-am" , "update" },
321+ {"git" , "-C" , workPath , "push" , upstreamPath , "HEAD" },
322+ } {
323+ assert .NoError (t , exec .Command (args [0 ], args [1 :]... ).Run ())
324+ }
325+ newSHAOut , err := exec .Command ("git" , "-C" , workPath , "rev-parse" , "HEAD" ).Output ()
326+ assert .NoError (t , err )
327+ newSHA := strings .TrimSpace (string (newSHAOut ))
328+
329+ holdSem := func (t * testing.T , fetch func () error ) error {
330+ t .Helper ()
331+ release := make (chan struct {})
332+ entered := make (chan struct {})
333+ holderDone := make (chan error , 1 )
334+ go func () {
335+ holderDone <- repo .WithFetchExclusion (ctx , func () error {
336+ close (entered )
337+ <- release
338+ return nil
339+ })
340+ }()
341+ <- entered
342+ fetchDone := make (chan error , 1 )
343+ go func () { fetchDone <- fetch () }()
344+ time .Sleep (50 * time .Millisecond )
345+ close (release )
346+ assert .NoError (t , <- holderDone )
347+ return <- fetchDone
348+ }
314349
315- // Advance upstream so the mirror is behind.
316- workPath := filepath .Join (tmpDir , "work" )
317- assert .NoError (t , os .WriteFile (filepath .Join (workPath , "f.txt" ), []byte ("y" ), 0o644 ))
318- for _ , args := range [][]string {
319- {"git" , "-C" , workPath , "commit" , "-am" , "update" },
320- {"git" , "-C" , workPath , "push" , upstreamPath , "HEAD" },
321- } {
322- assert .NoError (t , exec .Command (args [0 ], args [1 :]... ).Run ())
350+ fetch := repo .Fetch
351+ if verified {
352+ fetch = repo .FetchVerified
353+ }
354+ assert .NoError (t , holdSem (t , func () error { return fetch (ctx ) }))
355+ assert .True (t , repo .HasCommit (ctx , newSHA ))
356+ })
323357 }
324- newSHAOut , err := exec .Command ("git" , "-C" , workPath , "rev-parse" , "HEAD" ).Output ()
325- assert .NoError (t , err )
326- newSHA := strings .TrimSpace (string (newSHAOut ))
327-
328- holdSem := func (t * testing.T , fetch func () error ) error {
329- t .Helper ()
330- release := make (chan struct {})
331- holderDone := make (chan error , 1 )
332- go func () {
333- holderDone <- repo .WithFetchExclusion (ctx , func () error {
334- <- release
335- return nil
336- })
337- }()
338- time .Sleep (20 * time .Millisecond )
339- fetchDone := make (chan error , 1 )
340- go func () { fetchDone <- fetch () }()
341- time .Sleep (50 * time .Millisecond )
342- close (release )
343- assert .NoError (t , <- holderDone )
344- return <- fetchDone
345- }
346-
347- // Fetch coalesces with the semaphore holder even though the holder was
348- // not fetching, so the mirror stays behind.
349- assert .NoError (t , holdSem (t , func () error { return repo .Fetch (ctx ) }))
350- assert .False (t , repo .HasCommit (ctx , newSHA ))
351-
352- // FetchVerified waits for the holder and then runs its own fetch.
353- assert .NoError (t , holdSem (t , func () error { return repo .FetchVerified (ctx ) }))
354- assert .True (t , repo .HasCommit (ctx , newSHA ))
355358}
356359
357360func TestParseGitRefs (t * testing.T ) {
0 commit comments