gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2025 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package gitrepo
  4. import (
  5. "context"
  6. "errors"
  7. "io"
  8. "time"
  9. "code.gitea.io/gitea/modules/git"
  10. "code.gitea.io/gitea/modules/git/gitcmd"
  11. giturl "code.gitea.io/gitea/modules/git/url"
  12. "code.gitea.io/gitea/modules/globallock"
  13. "code.gitea.io/gitea/modules/util"
  14. )
  15. type RemoteOption string
  16. const (
  17. RemoteOptionMirrorPush RemoteOption = "--mirror=push"
  18. RemoteOptionMirrorFetch RemoteOption = "--mirror=fetch"
  19. )
  20. func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL string, options ...RemoteOption) error {
  21. return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
  22. cmd := gitcmd.NewCommand("remote", "add")
  23. if len(options) > 0 {
  24. switch options[0] {
  25. case RemoteOptionMirrorPush:
  26. cmd.AddArguments("--mirror=push")
  27. case RemoteOptionMirrorFetch:
  28. cmd.AddArguments("--mirror=fetch")
  29. default:
  30. return errors.New("unknown remote option: " + string(options[0]))
  31. }
  32. }
  33. _, _, err := cmd.
  34. AddDynamicArguments(remoteName, remoteURL).
  35. RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
  36. return err
  37. })
  38. }
  39. func GitRemoteRemove(ctx context.Context, repo Repository, remoteName string) error {
  40. return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
  41. cmd := gitcmd.NewCommand("remote", "rm").AddDynamicArguments(remoteName)
  42. _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
  43. return err
  44. })
  45. }
  46. // GitRemoteGetURL returns the url of a specific remote of the repository.
  47. func GitRemoteGetURL(ctx context.Context, repo Repository, remoteName string) (*giturl.GitURL, error) {
  48. addr, err := git.GetRemoteAddress(ctx, repoPath(repo), remoteName)
  49. if err != nil {
  50. return nil, err
  51. }
  52. if addr == "" {
  53. return nil, util.NewNotExistErrorf("remote '%s' does not exist", remoteName)
  54. }
  55. return giturl.ParseGitURL(addr)
  56. }
  57. // GitRemotePrune prunes the remote branches that no longer exist in the remote repository.
  58. func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error {
  59. return gitcmd.NewCommand("remote", "prune").AddDynamicArguments(remoteName).
  60. Run(ctx, &gitcmd.RunOpts{
  61. Timeout: timeout,
  62. Dir: repoPath(repo),
  63. Stdout: stdout,
  64. Stderr: stderr,
  65. })
  66. }
  67. // GitRemoteUpdatePrune updates the remote branches and prunes the ones that no longer exist in the remote repository.
  68. func GitRemoteUpdatePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error {
  69. return gitcmd.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName).
  70. Run(ctx, &gitcmd.RunOpts{
  71. Timeout: timeout,
  72. Dir: repoPath(repo),
  73. Stdout: stdout,
  74. Stderr: stderr,
  75. })
  76. }