code.gitea.io/gitea@v1.19.3/modules/repository/push.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repository 5 6 import ( 7 "context" 8 "strings" 9 10 repo_model "code.gitea.io/gitea/models/repo" 11 "code.gitea.io/gitea/modules/git" 12 ) 13 14 // PushUpdateOptions defines the push update options 15 type PushUpdateOptions struct { 16 PusherID int64 17 PusherName string 18 RepoUserName string 19 RepoName string 20 RefFullName string // branch, tag or other name to push 21 OldCommitID string 22 NewCommitID string 23 } 24 25 // IsNewRef return true if it's a first-time push to a branch, tag or etc. 26 func (opts *PushUpdateOptions) IsNewRef() bool { 27 return opts.OldCommitID == git.EmptySHA 28 } 29 30 // IsDelRef return true if it's a deletion to a branch or tag 31 func (opts *PushUpdateOptions) IsDelRef() bool { 32 return opts.NewCommitID == git.EmptySHA 33 } 34 35 // IsUpdateRef return true if it's an update operation 36 func (opts *PushUpdateOptions) IsUpdateRef() bool { 37 return !opts.IsNewRef() && !opts.IsDelRef() 38 } 39 40 // IsTag return true if it's an operation to a tag 41 func (opts *PushUpdateOptions) IsTag() bool { 42 return strings.HasPrefix(opts.RefFullName, git.TagPrefix) 43 } 44 45 // IsNewTag return true if it's a creation to a tag 46 func (opts *PushUpdateOptions) IsNewTag() bool { 47 return opts.IsTag() && opts.IsNewRef() 48 } 49 50 // IsDelTag return true if it's a deletion to a tag 51 func (opts *PushUpdateOptions) IsDelTag() bool { 52 return opts.IsTag() && opts.IsDelRef() 53 } 54 55 // IsBranch return true if it's a push to branch 56 func (opts *PushUpdateOptions) IsBranch() bool { 57 return strings.HasPrefix(opts.RefFullName, git.BranchPrefix) 58 } 59 60 // IsNewBranch return true if it's the first-time push to a branch 61 func (opts *PushUpdateOptions) IsNewBranch() bool { 62 return opts.IsBranch() && opts.IsNewRef() 63 } 64 65 // IsUpdateBranch return true if it's not the first push to a branch 66 func (opts *PushUpdateOptions) IsUpdateBranch() bool { 67 return opts.IsBranch() && opts.IsUpdateRef() 68 } 69 70 // IsDelBranch return true if it's a deletion to a branch 71 func (opts *PushUpdateOptions) IsDelBranch() bool { 72 return opts.IsBranch() && opts.IsDelRef() 73 } 74 75 // TagName returns simple tag name if it's an operation to a tag 76 func (opts *PushUpdateOptions) TagName() string { 77 return opts.RefFullName[len(git.TagPrefix):] 78 } 79 80 // BranchName returns simple branch name if it's an operation to branch 81 func (opts *PushUpdateOptions) BranchName() string { 82 return opts.RefFullName[len(git.BranchPrefix):] 83 } 84 85 // RefName returns simple name for ref 86 func (opts *PushUpdateOptions) RefName() string { 87 if strings.HasPrefix(opts.RefFullName, git.TagPrefix) { 88 return opts.RefFullName[len(git.TagPrefix):] 89 } else if strings.HasPrefix(opts.RefFullName, git.BranchPrefix) { 90 return opts.RefFullName[len(git.BranchPrefix):] 91 } 92 return "" 93 } 94 95 // RepoFullName returns repo full name 96 func (opts *PushUpdateOptions) RepoFullName() string { 97 return opts.RepoUserName + "/" + opts.RepoName 98 } 99 100 // IsForcePush detect if a push is a force push 101 func IsForcePush(ctx context.Context, opts *PushUpdateOptions) (bool, error) { 102 if !opts.IsUpdateBranch() { 103 return false, nil 104 } 105 106 output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(opts.OldCommitID, "^"+opts.NewCommitID). 107 RunStdString(&git.RunOpts{Dir: repo_model.RepoPath(opts.RepoUserName, opts.RepoName)}) 108 if err != nil { 109 return false, err 110 } else if len(output) > 0 { 111 return true, nil 112 } 113 return false, nil 114 }