gitea源码

remote.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package git
  4. import (
  5. "context"
  6. "fmt"
  7. "net/url"
  8. "strings"
  9. "code.gitea.io/gitea/modules/git/gitcmd"
  10. "code.gitea.io/gitea/modules/util"
  11. )
  12. // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name
  13. func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) {
  14. var cmd *gitcmd.Command
  15. if DefaultFeatures().CheckVersionAtLeast("2.7") {
  16. cmd = gitcmd.NewCommand("remote", "get-url").AddDynamicArguments(remoteName)
  17. } else {
  18. cmd = gitcmd.NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
  19. }
  20. result, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
  21. if err != nil {
  22. return "", err
  23. }
  24. if len(result) > 0 {
  25. result = result[:len(result)-1]
  26. }
  27. return result, nil
  28. }
  29. // ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
  30. type ErrInvalidCloneAddr struct {
  31. Host string
  32. IsURLError bool
  33. IsInvalidPath bool
  34. IsProtocolInvalid bool
  35. IsPermissionDenied bool
  36. LocalPath bool
  37. }
  38. // IsErrInvalidCloneAddr checks if an error is a ErrInvalidCloneAddr.
  39. func IsErrInvalidCloneAddr(err error) bool {
  40. _, ok := err.(*ErrInvalidCloneAddr)
  41. return ok
  42. }
  43. func (err *ErrInvalidCloneAddr) Error() string {
  44. if err.IsInvalidPath {
  45. return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided path is invalid", err.Host)
  46. }
  47. if err.IsProtocolInvalid {
  48. return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url protocol is not allowed", err.Host)
  49. }
  50. if err.IsPermissionDenied {
  51. return fmt.Sprintf("migration/cloning from '%s' is not allowed.", err.Host)
  52. }
  53. if err.IsURLError {
  54. return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url is invalid", err.Host)
  55. }
  56. return fmt.Sprintf("migration/cloning from '%s' is not allowed", err.Host)
  57. }
  58. func (err *ErrInvalidCloneAddr) Unwrap() error {
  59. return util.ErrInvalidArgument
  60. }
  61. // IsRemoteNotExistError checks the prefix of the error message to see whether a remote does not exist.
  62. func IsRemoteNotExistError(err error) bool {
  63. // see: https://github.com/go-gitea/gitea/issues/32889#issuecomment-2571848216
  64. // Should not add space in the end, sometimes git will add a `:`
  65. prefix1 := "exit status 128 - fatal: No such remote" // git < 2.30
  66. prefix2 := "exit status 2 - error: No such remote" // git >= 2.30
  67. return strings.HasPrefix(err.Error(), prefix1) || strings.HasPrefix(err.Error(), prefix2)
  68. }
  69. // ParseRemoteAddr checks if given remote address is valid,
  70. // and returns composed URL with needed username and password.
  71. func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
  72. remoteAddr = strings.TrimSpace(remoteAddr)
  73. // Remote address can be HTTP/HTTPS/Git URL or local path.
  74. if strings.HasPrefix(remoteAddr, "http://") ||
  75. strings.HasPrefix(remoteAddr, "https://") ||
  76. strings.HasPrefix(remoteAddr, "git://") {
  77. u, err := url.Parse(remoteAddr)
  78. if err != nil {
  79. return "", &ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr}
  80. }
  81. if len(authUsername)+len(authPassword) > 0 {
  82. u.User = url.UserPassword(authUsername, authPassword)
  83. }
  84. remoteAddr = u.String()
  85. }
  86. return remoteAddr, nil
  87. }