You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.9 KiB

  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. package repository
  5. import (
  6. "fmt"
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/modules/git"
  9. )
  10. // GetBranch returns a branch by its name
  11. func GetBranch(repo *models.Repository, branch string) (*git.Branch, error) {
  12. gitRepo, err := git.OpenRepository(repo.RepoPath())
  13. if err != nil {
  14. return nil, err
  15. }
  16. defer gitRepo.Close()
  17. return gitRepo.GetBranch(branch)
  18. }
  19. // GetBranches returns all the branches of a repository
  20. func GetBranches(repo *models.Repository) ([]*git.Branch, error) {
  21. return git.GetBranchesByPath(repo.RepoPath())
  22. }
  23. // checkBranchName validates branch name with existing repository branches
  24. func checkBranchName(repo *models.Repository, name string) error {
  25. gitRepo, err := git.OpenRepository(repo.RepoPath())
  26. if err != nil {
  27. return err
  28. }
  29. defer gitRepo.Close()
  30. branches, err := GetBranches(repo)
  31. if err != nil {
  32. return err
  33. }
  34. for _, branch := range branches {
  35. if branch.Name == name {
  36. return models.ErrBranchAlreadyExists{
  37. BranchName: branch.Name,
  38. }
  39. } else if (len(branch.Name) < len(name) && branch.Name+"/" == name[0:len(branch.Name)+1]) ||
  40. (len(branch.Name) > len(name) && name+"/" == branch.Name[0:len(name)+1]) {
  41. return models.ErrBranchNameConflict{
  42. BranchName: branch.Name,
  43. }
  44. }
  45. }
  46. if _, err := gitRepo.GetTag(name); err == nil {
  47. return models.ErrTagAlreadyExists{
  48. TagName: name,
  49. }
  50. }
  51. return nil
  52. }
  53. // CreateNewBranch creates a new repository branch
  54. func CreateNewBranch(doer *models.User, repo *models.Repository, oldBranchName, branchName string) (err error) {
  55. // Check if branch name can be used
  56. if err := checkBranchName(repo, branchName); err != nil {
  57. return err
  58. }
  59. if !git.IsBranchExist(repo.RepoPath(), oldBranchName) {
  60. return models.ErrBranchDoesNotExist{
  61. BranchName: oldBranchName,
  62. }
  63. }
  64. if err := git.Push(repo.RepoPath(), git.PushOptions{
  65. Remote: repo.RepoPath(),
  66. Branch: fmt.Sprintf("%s:%s%s", oldBranchName, git.BranchPrefix, branchName),
  67. Env: models.PushingEnvironment(doer, repo),
  68. }); err != nil {
  69. if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
  70. return err
  71. }
  72. return fmt.Errorf("Push: %v", err)
  73. }
  74. return nil
  75. }
  76. // CreateNewBranchFromCommit creates a new repository branch
  77. func CreateNewBranchFromCommit(doer *models.User, repo *models.Repository, commit, branchName string) (err error) {
  78. // Check if branch name can be used
  79. if err := checkBranchName(repo, branchName); err != nil {
  80. return err
  81. }
  82. if err := git.Push(repo.RepoPath(), git.PushOptions{
  83. Remote: repo.RepoPath(),
  84. Branch: fmt.Sprintf("%s:%s%s", commit, git.BranchPrefix, branchName),
  85. Env: models.PushingEnvironment(doer, repo),
  86. }); err != nil {
  87. if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
  88. return err
  89. }
  90. return fmt.Errorf("Push: %v", err)
  91. }
  92. return nil
  93. }