@@ -263,12 +263,12 @@ func (h *GitopiaHandler) Push(remote *core.Remote, refsToPush []core.RefToPush)
263263 remoteURL := fmt .Sprintf ("%v/%v.git" , gitServerHost , h .remoteRepository .Id )
264264 lfsURL := remoteURL // Use same URL for LFS
265265
266- var pushRefspecs []string
267- var deleteBranches , deleteTags []string
266+ var allRefspecs []string
268267 var setBranches []gitopiatypes.MsgMultiSetBranch_Branch
269268 var setTags []gitopiatypes.MsgMultiSetTag_Tag
269+ var deleteBranches , deleteTags []string
270270 isForce := false
271- var res []string // To return the refs that were processed
271+ var res []string
272272 var packfileCid string
273273
274274 packfileRes , err := h .storageClient .RepositoryPackfile (context .Background (), & storagetypes.QueryRepositoryPackfileRequest {
@@ -278,21 +278,24 @@ func (h *GitopiaHandler) Push(remote *core.Remote, refsToPush []core.RefToPush)
278278 packfileCid = packfileRes .Packfile .Cid
279279 }
280280
281- // --- First Pass: Collect refspecs and deletions ---
281+ // --- First Pass: Collect all refspecs and metadata ---
282282 for _ , ref := range refsToPush {
283283 if ref .Local == "" { // This is a delete operation
284+ var refNameToDelete string
284285 if strings .HasPrefix (ref .Remote , branchPrefix ) {
285- remoteBranchName := strings .TrimPrefix (ref .Remote , branchPrefix )
286- if remoteBranchName == h .remoteRepository .DefaultBranch {
287- return nil , fmt .Errorf ("fatal: cannot delete default branch, %v" , remoteBranchName )
288- }
289- deleteBranches = append (deleteBranches , remoteBranchName )
290- res = append (res , ref .Remote )
286+ refNameToDelete = strings .TrimPrefix (ref .Remote , branchPrefix )
287+ deleteBranches = append (deleteBranches , refNameToDelete )
291288 } else if strings .HasPrefix (ref .Remote , tagPrefix ) {
292- remoteTagName := strings .TrimPrefix (ref .Remote , tagPrefix )
293- deleteTags = append (deleteTags , remoteTagName )
294- res = append (res , ref .Remote )
289+ refNameToDelete = strings .TrimPrefix (ref .Remote , tagPrefix )
290+ deleteTags = append (deleteTags , refNameToDelete )
291+ } else {
292+ continue // Skip unknown ref types
295293 }
294+
295+ // Add to the list of commands for the git server
296+ // The syntax for delete is ":<refname>"
297+ allRefspecs = append (allRefspecs , ":" + ref .Remote )
298+ res = append (res , ref .Remote )
296299 continue
297300 }
298301
@@ -303,57 +306,10 @@ func (h *GitopiaHandler) Push(remote *core.Remote, refsToPush []core.RefToPush)
303306 isForce = true
304307 }
305308
306- pushRefspecs = append (pushRefspecs , fmt .Sprintf ("%s:%s" , ref .Local , ref .Remote ))
307- }
308-
309- // --- Execute a single Git Push if there's anything to push ---
310- if len (pushRefspecs ) > 0 {
311- if h .wallet .Type () == wallet .LEDGER {
312- remote .Logger .Println ("Please sign the git server request on your ledger device." )
313- }
314-
315- data := []byte ("test" )
316- signature , err := h .wallet .SignData (data )
317- if err != nil {
318- return nil , errors .Wrap (err , "error signing data" )
319- }
320- credential := fmt .Sprintf ("%s:%s" , h .wallet .Address (), signature )
321-
322- args := []string {
323- "-c" , fmt .Sprintf ("http.extraheader=Authorization: Basic %s" , base64 .StdEncoding .EncodeToString ([]byte (credential ))),
324- "-c" , "credential.helper=" ,
325- "-c" , "credential.helper=gitopia" ,
326- "-c" , fmt .Sprintf ("lfs.url=%s" , lfsURL ),
327- "push" ,
328- "--no-verify" , // Keep this to prevent the double-hook call
329- remoteURL ,
330- }
331-
332- // Add all refspecs to the command
333- args = append (args , pushRefspecs ... )
309+ // Add to the list of commands for the git server
310+ allRefspecs = append (allRefspecs , fmt .Sprintf ("%s:%s" , ref .Local , ref .Remote ))
334311
335- if isForce {
336- args = append (args , "--force" )
337- }
338-
339- cmd := core .GitCommand ("git" , args ... )
340- if err := cmd .Run (); err != nil {
341- return nil , errors .Wrap (err , "error pushing to remote repository" )
342- }
343- }
344-
345- // --- Second Pass: Collect metadata for Gitopia transaction ---
346- for _ , ref := range refsToPush {
347- if ref .Local == "" {
348- continue // Deletes already handled
349- }
350-
351- localRef := ref .Local
352- if strings .HasPrefix (localRef , "+" ) {
353- localRef = strings .TrimPrefix (localRef , "+" )
354- }
355-
356- // Update ref on gitopia
312+ // Collect metadata for the blockchain transaction
357313 if strings .HasPrefix (localRef , branchPrefix ) {
358314 localCommitHash , err := remote .Repo .ResolveRevision (plumbing .Revision (localRef ))
359315 if err != nil {
@@ -391,34 +347,70 @@ func (h *GitopiaHandler) Push(remote *core.Remote, refsToPush []core.RefToPush)
391347 }
392348
393349 res = append (res , ref .Remote )
394- } else {
395- return nil , fmt .Errorf ("fatal: invalid refspec, %v" , ref )
396350 }
397351 }
398352
399- var msg []sdk.Msg
353+ // --- Execute a single Git Push if there's anything to do ---
354+ if len (allRefspecs ) > 0 {
355+ if h .wallet .Type () == wallet .LEDGER {
356+ remote .Logger .Println ("Please sign the git server request on your ledger device." )
357+ }
400358
401- // Approve packfile update
402- packfileUpdateProposalRes , err := h .storageClient .PackfileUpdateProposal (context .Background (), & storagetypes.QueryPackfileUpdateProposalRequest {
403- RepositoryId : h .remoteRepository .Id ,
404- User : h .wallet .Address (),
405- })
406- if err != nil {
407- return nil , err
408- }
409- msg = append (msg , storagetypes .NewMsgApproveRepositoryPackfileUpdate (h .wallet .Address (), packfileUpdateProposalRes .PackfileUpdateProposal .Id ))
359+ data := []byte ("test" )
360+ signature , err := h .wallet .SignData (data )
361+ if err != nil {
362+ return nil , errors .Wrap (err , "error signing data" )
363+ }
364+ credential := fmt .Sprintf ("%s:%s" , h .wallet .Address (), signature )
410365
411- lfsObjectUpdateProposalRes , err := h .storageClient .LFSObjectUpdateProposalsByRepositoryId (context .Background (), & storagetypes.QueryLFSObjectUpdateProposalsByRepositoryIdRequest {
412- RepositoryId : h .remoteRepository .Id ,
413- User : h .wallet .Address (),
414- })
415- if err != nil {
416- return nil , err
366+ args := []string {
367+ "-c" , fmt .Sprintf ("http.extraheader=Authorization: Basic %s" , base64 .StdEncoding .EncodeToString ([]byte (credential ))),
368+ "-c" , "credential.helper=" ,
369+ "-c" , "credential.helper=gitopia" ,
370+ "-c" , fmt .Sprintf ("lfs.url=%s" , lfsURL ),
371+ "push" ,
372+ "--no-verify" , // Keep this to prevent the double-hook call
373+ remoteURL ,
374+ }
375+
376+ args = append (args , allRefspecs ... )
377+
378+ if isForce {
379+ args = append (args , "--force" )
380+ }
381+
382+ cmd := core .GitCommand ("git" , args ... )
383+ if err := cmd .Run (); err != nil {
384+ return nil , errors .Wrap (err , "error pushing to remote repository" )
385+ }
417386 }
418387
419- // Approve LFS object update
420- for _ , lfsObjectUpdateProposal := range lfsObjectUpdateProposalRes .LfsObjectProposals {
421- msg = append (msg , storagetypes .NewMsgApproveLFSObjectUpdate (h .wallet .Address (), lfsObjectUpdateProposal .Id ))
388+ var msg []sdk.Msg
389+
390+ // Only try to approve packfile/LFS updates if we actually pushed something.
391+ if len (allRefspecs ) > 0 {
392+ // Approve packfile update
393+ packfileUpdateProposalRes , err := h .storageClient .PackfileUpdateProposal (context .Background (), & storagetypes.QueryPackfileUpdateProposalRequest {
394+ RepositoryId : h .remoteRepository .Id ,
395+ User : h .wallet .Address (),
396+ })
397+ if err != nil {
398+ return nil , err
399+ }
400+ msg = append (msg , storagetypes .NewMsgApproveRepositoryPackfileUpdate (h .wallet .Address (), packfileUpdateProposalRes .PackfileUpdateProposal .Id ))
401+
402+ lfsObjectUpdateProposalRes , err := h .storageClient .LFSObjectUpdateProposalsByRepositoryId (context .Background (), & storagetypes.QueryLFSObjectUpdateProposalsByRepositoryIdRequest {
403+ RepositoryId : h .remoteRepository .Id ,
404+ User : h .wallet .Address (),
405+ })
406+ if err != nil {
407+ return nil , err
408+ }
409+
410+ // Approve LFS object update
411+ for _ , lfsObjectUpdateProposal := range lfsObjectUpdateProposalRes .LfsObjectProposals {
412+ msg = append (msg , storagetypes .NewMsgApproveLFSObjectUpdate (h .wallet .Address (), lfsObjectUpdateProposal .Id ))
413+ }
422414 }
423415
424416 if len (setBranches ) > 0 {
@@ -446,6 +438,12 @@ func (h *GitopiaHandler) Push(remote *core.Remote, refsToPush []core.RefToPush)
446438 }, deleteTags ))
447439 }
448440
441+ // Make sure we don't send an empty transaction
442+ if len (msg ) == 0 {
443+ remote .Logger .Println ("Nothing to update on Gitopia." )
444+ return res , nil
445+ }
446+
449447 if h .wallet .Type () == wallet .LEDGER {
450448 remote .Logger .Println ("Please sign the gitopia transaction on your ledger device." )
451449 }
0 commit comments