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.

104 lines
3.2 KiB

  1. // Copyright 2015 The Gogs 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 git
  5. import (
  6. "container/list"
  7. "fmt"
  8. "strings"
  9. "time"
  10. "github.com/Unknwon/com"
  11. )
  12. type PullRequestInfo struct {
  13. MergeBase string
  14. Commits *list.List
  15. // Diff *Diff
  16. NumFiles int
  17. }
  18. // GetMergeBase checks and returns merge base of two branches.
  19. func (repo *Repository) GetMergeBase(remoteBranch, headBranch string) (string, error) {
  20. // Get merge base commit.
  21. stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch)
  22. if err != nil {
  23. return "", fmt.Errorf("get merge base: %v", concatenateError(err, stderr))
  24. }
  25. return strings.TrimSpace(stdout), nil
  26. }
  27. // AddRemote adds a remote to repository.
  28. func (repo *Repository) AddRemote(name, path string) error {
  29. _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", name, path)
  30. if err != nil {
  31. return fmt.Errorf("add remote(%s - %s): %v", name, path, concatenateError(err, stderr))
  32. }
  33. return nil
  34. }
  35. // RemoveRemote removes a remote from repository.
  36. func (repo *Repository) RemoveRemote(name string) error {
  37. _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "remove", name)
  38. if err != nil {
  39. return fmt.Errorf("remove remote(%s): %v", name, concatenateError(err, stderr))
  40. }
  41. return nil
  42. }
  43. // GetPullRequestInfo generates and returns pull request information
  44. // between base and head branches of repositories.
  45. func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) {
  46. // Add a temporary remote.
  47. tmpRemote := com.ToStr(time.Now().UnixNano())
  48. if err = repo.AddRemote(tmpRemote, basePath); err != nil {
  49. return nil, fmt.Errorf("AddRemote: %v", err)
  50. }
  51. defer func() {
  52. repo.RemoveRemote(tmpRemote)
  53. }()
  54. remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch
  55. prInfo := new(PullRequestInfo)
  56. prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch)
  57. if err != nil {
  58. return nil, fmt.Errorf("GetMergeBase: %v", err)
  59. }
  60. stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat)
  61. if err != nil {
  62. return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr))
  63. }
  64. prInfo.Commits, err = parsePrettyFormatLog(repo, []byte(stdout))
  65. if err != nil {
  66. return nil, fmt.Errorf("parsePrettyFormatLog: %v", err)
  67. }
  68. // Count number of changed files.
  69. stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", remoteBranch+"..."+headBranch)
  70. if err != nil {
  71. return nil, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
  72. }
  73. prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1
  74. return prInfo, nil
  75. }
  76. // GetPatch generates and returns patch data between given branches.
  77. func (repo *Repository) GetPatch(mergeBase, headBranch string) ([]byte, error) {
  78. stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", "--binary", mergeBase, headBranch)
  79. if err != nil {
  80. return nil, concatenateError(err, string(stderr))
  81. }
  82. return stdout, nil
  83. }
  84. // Merge merges pull request from head repository and branch.
  85. func (repo *Repository) Merge(headRepoPath string, baseBranch, headBranch string) error {
  86. return nil
  87. }