1// Copyright 2020 The Gitea Authors. All rights reserved. 2// Use of this source code is governed by a MIT-style 3// license that can be found in the LICENSE file. 4 5package repository 6 7import ( 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 15type 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. 26func (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 31func (opts *PushUpdateOptions) IsDelRef() bool { 32 return opts.NewCommitID == git.EmptySHA 33} 34 35// IsUpdateRef return true if it's an update operation 36func (opts *PushUpdateOptions) IsUpdateRef() bool { 37 return !opts.IsNewRef() && !opts.IsDelRef() 38} 39 40// IsTag return true if it's an operation to a tag 41func (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 46func (opts *PushUpdateOptions) IsNewTag() bool { 47 return opts.IsTag() && opts.IsNewRef() 48} 49 50// IsDelTag return true if it's a deletion to a tag 51func (opts *PushUpdateOptions) IsDelTag() bool { 52 return opts.IsTag() && opts.IsDelRef() 53} 54 55// IsBranch return true if it's a push to branch 56func (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 61func (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 66func (opts *PushUpdateOptions) IsUpdateBranch() bool { 67 return opts.IsBranch() && opts.IsUpdateRef() 68} 69 70// IsDelBranch return true if it's a deletion to a branch 71func (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 76func (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 81func (opts *PushUpdateOptions) BranchName() string { 82 return opts.RefFullName[len(git.BranchPrefix):] 83} 84 85// RefName returns simple name for ref 86func (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 96func (opts *PushUpdateOptions) RepoFullName() string { 97 return opts.RepoUserName + "/" + opts.RepoName 98} 99 100// IsForcePush detect if a push is a force push 101func IsForcePush(opts *PushUpdateOptions) (bool, error) { 102 if !opts.IsUpdateBranch() { 103 return false, nil 104 } 105 106 output, err := git.NewCommand("rev-list", "--max-count=1", opts.OldCommitID, "^"+opts.NewCommitID). 107 RunInDir(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} 115