@@ -252,8 +252,8 @@ def test_fetch_depth_one(testrepo):
252252
253253def test_transfer_progress (emptyrepo ):
254254 class MyCallbacks (pygit2 .RemoteCallbacks ):
255- def transfer_progress (emptyrepo , stats ):
256- emptyrepo .tp = stats
255+ def transfer_progress (self , stats ):
256+ self .tp = stats
257257
258258 callbacks = MyCallbacks ()
259259 remote = emptyrepo .remotes [0 ]
@@ -362,6 +362,59 @@ def test_push_when_up_to_date_succeeds(origin, clone, remote):
362362 assert origin_tip == clone_tip
363363
364364
365+ def test_push_transfer_progress (origin , clone , remote ):
366+ tip = clone [clone .head .target ]
367+ new_tip_id = clone .create_commit (
368+ 'refs/heads/master' ,
369+ tip .author ,
370+ tip .author ,
371+ 'empty commit' ,
372+ tip .tree .id ,
373+ [tip .id ],
374+ )
375+
376+ # NOTE: We're currently not testing bytes_pushed due to a bug in libgit2
377+ # 1.9.0: it passes a junk value for bytes_pushed when pushing to a remote
378+ # on the local filesystem, as is the case in this unit test. (When pushing
379+ # to a remote over the network, the value is correct.)
380+ class MyCallbacks (pygit2 .RemoteCallbacks ):
381+ def push_transfer_progress (self , objects_pushed , total_objects , bytes_pushed ):
382+ self .objects_pushed = objects_pushed
383+ self .total_objects = total_objects
384+
385+ assert origin .branches ['master' ].target == tip .id
386+
387+ callbacks = MyCallbacks ()
388+ remote .push (['refs/heads/master' ], callbacks = callbacks )
389+ assert callbacks .objects_pushed == 1
390+ assert callbacks .total_objects == 1
391+ assert origin .branches ['master' ].target == new_tip_id
392+
393+
394+ def test_push_interrupted_from_callbacks (origin , clone , remote ):
395+ tip = clone [clone .head .target ]
396+ clone .create_commit (
397+ 'refs/heads/master' ,
398+ tip .author ,
399+ tip .author ,
400+ 'empty commit' ,
401+ tip .tree .id ,
402+ [tip .id ],
403+ )
404+
405+ class MyCallbacks (pygit2 .RemoteCallbacks ):
406+ def push_transfer_progress (self , objects_pushed , total_objects , bytes_pushed ):
407+ raise InterruptedError ('retreat! retreat!' )
408+
409+ assert origin .branches ['master' ].target == tip .id
410+
411+ callbacks = MyCallbacks ()
412+ with pytest .raises (InterruptedError , match = 'retreat! retreat!' ):
413+ remote .push (['refs/heads/master' ], callbacks = callbacks )
414+
415+ assert origin .branches ['master' ].target == tip .id
416+
417+
365418def test_push_non_fast_forward_commits_to_remote_fails (origin , clone , remote ):
366419 tip = origin [origin .head .target ]
367420 origin .create_commit (
@@ -386,22 +439,31 @@ def test_push_non_fast_forward_commits_to_remote_fails(origin, clone, remote):
386439 remote .push (['refs/heads/master' ])
387440
388441
389- @patch .object (pygit2 .callbacks , 'RemoteCallbacks' )
390- def test_push_options (mock_callbacks , origin , clone , remote ):
391- remote .push (['refs/heads/master' ])
392- remote_push_options = mock_callbacks .return_value .push_options .remote_push_options
442+ def test_push_options (origin , clone , remote ):
443+ from pygit2 import RemoteCallbacks
444+
445+ callbacks = RemoteCallbacks ()
446+ remote .push (['refs/heads/master' ], callbacks )
447+ remote_push_options = callbacks .push_options .remote_push_options
393448 assert remote_push_options .count == 0
394449
395- remote .push (['refs/heads/master' ], push_options = [])
396- remote_push_options = mock_callbacks .return_value .push_options .remote_push_options
450+ callbacks = RemoteCallbacks ()
451+ remote .push (['refs/heads/master' ], callbacks , push_options = [])
452+ remote_push_options = callbacks .push_options .remote_push_options
397453 assert remote_push_options .count == 0
398454
399- remote .push (['refs/heads/master' ], push_options = ['foo' ])
400- remote_push_options = mock_callbacks .return_value .push_options .remote_push_options
455+ callbacks = RemoteCallbacks ()
456+ # Local remotes don't support push_options, so pushing will raise an error.
457+ # However, push_options should still be set in RemoteCallbacks.
458+ with pytest .raises (pygit2 .GitError , match = 'push-options not supported by remote' ):
459+ remote .push (['refs/heads/master' ], callbacks , push_options = ['foo' ])
460+ remote_push_options = callbacks .push_options .remote_push_options
401461 assert remote_push_options .count == 1
402462 # strings pointed to by remote_push_options.strings[] are already freed
403463
404- remote .push (['refs/heads/master' ], push_options = ['Option A' , 'Option B' ])
405- remote_push_options = mock_callbacks .return_value .push_options .remote_push_options
464+ callbacks = RemoteCallbacks ()
465+ with pytest .raises (pygit2 .GitError , match = 'push-options not supported by remote' ):
466+ remote .push (['refs/heads/master' ], callbacks , push_options = ['Opt A' , 'Opt B' ])
467+ remote_push_options = callbacks .push_options .remote_push_options
406468 assert remote_push_options .count == 2
407469 # strings pointed to by remote_push_options.strings[] are already freed
0 commit comments