code.gitea.io/gitea@v1.22.3/modules/git/repo_branch.go (about) 1 // Copyright 2015 The Gogs Authors. All rights reserved. 2 // Copyright 2018 The Gitea Authors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 5 package git 6 7 import ( 8 "context" 9 "errors" 10 "fmt" 11 "strings" 12 ) 13 14 // BranchPrefix base dir of the branch information file store on git 15 const BranchPrefix = "refs/heads/" 16 17 // IsReferenceExist returns true if given reference exists in the repository. 18 func IsReferenceExist(ctx context.Context, repoPath, name string) bool { 19 _, _, err := NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repoPath}) 20 return err == nil 21 } 22 23 // IsBranchExist returns true if given branch exists in the repository. 24 func IsBranchExist(ctx context.Context, repoPath, name string) bool { 25 return IsReferenceExist(ctx, repoPath, BranchPrefix+name) 26 } 27 28 // Branch represents a Git branch. 29 type Branch struct { 30 Name string 31 Path string 32 33 gitRepo *Repository 34 } 35 36 // GetHEADBranch returns corresponding branch of HEAD. 37 func (repo *Repository) GetHEADBranch() (*Branch, error) { 38 if repo == nil { 39 return nil, fmt.Errorf("nil repo") 40 } 41 stdout, _, err := NewCommand(repo.Ctx, "symbolic-ref", "HEAD").RunStdString(&RunOpts{Dir: repo.Path}) 42 if err != nil { 43 return nil, err 44 } 45 stdout = strings.TrimSpace(stdout) 46 47 if !strings.HasPrefix(stdout, BranchPrefix) { 48 return nil, fmt.Errorf("invalid HEAD branch: %v", stdout) 49 } 50 51 return &Branch{ 52 Name: stdout[len(BranchPrefix):], 53 Path: stdout, 54 gitRepo: repo, 55 }, nil 56 } 57 58 func GetDefaultBranch(ctx context.Context, repoPath string) (string, error) { 59 stdout, _, err := NewCommand(ctx, "symbolic-ref", "HEAD").RunStdString(&RunOpts{Dir: repoPath}) 60 if err != nil { 61 return "", err 62 } 63 stdout = strings.TrimSpace(stdout) 64 if !strings.HasPrefix(stdout, BranchPrefix) { 65 return "", errors.New("the HEAD is not a branch: " + stdout) 66 } 67 return strings.TrimPrefix(stdout, BranchPrefix), nil 68 } 69 70 // GetBranch returns a branch by it's name 71 func (repo *Repository) GetBranch(branch string) (*Branch, error) { 72 if !repo.IsBranchExist(branch) { 73 return nil, ErrBranchNotExist{branch} 74 } 75 return &Branch{ 76 Path: repo.Path, 77 Name: branch, 78 gitRepo: repo, 79 }, nil 80 } 81 82 // GetBranches returns a slice of *git.Branch 83 func (repo *Repository) GetBranches(skip, limit int) ([]*Branch, int, error) { 84 brs, countAll, err := repo.GetBranchNames(skip, limit) 85 if err != nil { 86 return nil, 0, err 87 } 88 89 branches := make([]*Branch, len(brs)) 90 for i := range brs { 91 branches[i] = &Branch{ 92 Path: repo.Path, 93 Name: brs[i], 94 gitRepo: repo, 95 } 96 } 97 98 return branches, countAll, nil 99 } 100 101 // DeleteBranchOptions Option(s) for delete branch 102 type DeleteBranchOptions struct { 103 Force bool 104 } 105 106 // DeleteBranch delete a branch by name on repository. 107 func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error { 108 cmd := NewCommand(repo.Ctx, "branch") 109 110 if opts.Force { 111 cmd.AddArguments("-D") 112 } else { 113 cmd.AddArguments("-d") 114 } 115 116 cmd.AddDashesAndList(name) 117 _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path}) 118 119 return err 120 } 121 122 // CreateBranch create a new branch 123 func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error { 124 cmd := NewCommand(repo.Ctx, "branch") 125 cmd.AddDashesAndList(branch, oldbranchOrCommit) 126 127 _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path}) 128 129 return err 130 } 131 132 // AddRemote adds a new remote to repository. 133 func (repo *Repository) AddRemote(name, url string, fetch bool) error { 134 cmd := NewCommand(repo.Ctx, "remote", "add") 135 if fetch { 136 cmd.AddArguments("-f") 137 } 138 cmd.AddDynamicArguments(name, url) 139 140 _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path}) 141 return err 142 } 143 144 // RemoveRemote removes a remote from repository. 145 func (repo *Repository) RemoveRemote(name string) error { 146 _, _, err := NewCommand(repo.Ctx, "remote", "rm").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path}) 147 return err 148 } 149 150 // GetCommit returns the head commit of a branch 151 func (branch *Branch) GetCommit() (*Commit, error) { 152 return branch.gitRepo.GetBranchCommit(branch.Name) 153 } 154 155 // RenameBranch rename a branch 156 func (repo *Repository) RenameBranch(from, to string) error { 157 _, _, err := NewCommand(repo.Ctx, "branch", "-m").AddDynamicArguments(from, to).RunStdString(&RunOpts{Dir: repo.Path}) 158 return err 159 }