gitea源码

repo_base_gogit.go 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2017 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. //go:build gogit
  5. package git
  6. import (
  7. "context"
  8. "path/filepath"
  9. gitealog "code.gitea.io/gitea/modules/log"
  10. "code.gitea.io/gitea/modules/setting"
  11. "code.gitea.io/gitea/modules/util"
  12. "github.com/go-git/go-billy/v5"
  13. "github.com/go-git/go-billy/v5/osfs"
  14. gogit "github.com/go-git/go-git/v5"
  15. "github.com/go-git/go-git/v5/plumbing"
  16. "github.com/go-git/go-git/v5/plumbing/cache"
  17. "github.com/go-git/go-git/v5/storage/filesystem"
  18. )
  19. const isGogit = true
  20. // Repository represents a Git repository.
  21. type Repository struct {
  22. Path string
  23. tagCache *ObjectCache[*Tag]
  24. gogitRepo *gogit.Repository
  25. gogitStorage *filesystem.Storage
  26. gpgSettings *GPGSettings
  27. Ctx context.Context
  28. LastCommitCache *LastCommitCache
  29. objectFormat ObjectFormat
  30. }
  31. // OpenRepository opens the repository at the given path within the context.Context
  32. func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
  33. repoPath, err := filepath.Abs(repoPath)
  34. if err != nil {
  35. return nil, err
  36. }
  37. exist, err := util.IsDir(repoPath)
  38. if err != nil {
  39. return nil, err
  40. }
  41. if !exist {
  42. return nil, util.NewNotExistErrorf("no such file or directory")
  43. }
  44. fs := osfs.New(repoPath)
  45. _, err = fs.Stat(".git")
  46. if err == nil {
  47. fs, err = fs.Chroot(".git")
  48. if err != nil {
  49. return nil, err
  50. }
  51. }
  52. // the "clone --shared" repo doesn't work well with go-git AlternativeFS, https://github.com/go-git/go-git/issues/1006
  53. // so use "/" for AlternatesFS, I guess it is the same behavior as current nogogit (no limitation or check for the "objects/info/alternates" paths), trust the "clone" command executed by the server.
  54. var altFs billy.Filesystem
  55. if setting.IsWindows {
  56. altFs = osfs.New(filepath.VolumeName(setting.RepoRootPath) + "\\") // TODO: does it really work for Windows? Need some time to check.
  57. } else {
  58. altFs = osfs.New("/")
  59. }
  60. storage := filesystem.NewStorageWithOptions(fs, cache.NewObjectLRUDefault(), filesystem.Options{KeepDescriptors: true, LargeObjectThreshold: setting.Git.LargeObjectThreshold, AlternatesFS: altFs})
  61. gogitRepo, err := gogit.Open(storage, fs)
  62. if err != nil {
  63. return nil, err
  64. }
  65. return &Repository{
  66. Path: repoPath,
  67. gogitRepo: gogitRepo,
  68. gogitStorage: storage,
  69. tagCache: newObjectCache[*Tag](),
  70. Ctx: ctx,
  71. objectFormat: ParseGogitHash(plumbing.ZeroHash).Type(),
  72. }, nil
  73. }
  74. // Close this repository, in particular close the underlying gogitStorage if this is not nil
  75. func (repo *Repository) Close() error {
  76. if repo == nil || repo.gogitStorage == nil {
  77. return nil
  78. }
  79. if err := repo.gogitStorage.Close(); err != nil {
  80. gitealog.Error("Error closing storage: %v", err)
  81. }
  82. repo.gogitStorage = nil
  83. repo.LastCommitCache = nil
  84. repo.tagCache = nil
  85. return nil
  86. }
  87. // GoGitRepo gets the go-git repo representation
  88. func (repo *Repository) GoGitRepo() *gogit.Repository {
  89. return repo.gogitRepo
  90. }