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.

repo_base_gogit.go 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. "errors"
  9. "path/filepath"
  10. gitealog "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/setting"
  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/cache"
  16. "github.com/go-git/go-git/v5/storage/filesystem"
  17. )
  18. // Repository represents a Git repository.
  19. type Repository struct {
  20. Path string
  21. tagCache *ObjectCache
  22. gogitRepo *gogit.Repository
  23. gogitStorage *filesystem.Storage
  24. gpgSettings *GPGSettings
  25. Ctx context.Context
  26. LastCommitCache *LastCommitCache
  27. }
  28. // openRepositoryWithDefaultContext opens the repository at the given path with DefaultContext.
  29. func openRepositoryWithDefaultContext(repoPath string) (*Repository, error) {
  30. return OpenRepository(DefaultContext, repoPath)
  31. }
  32. // OpenRepository opens the repository at the given path within the context.Context
  33. func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
  34. repoPath, err := filepath.Abs(repoPath)
  35. if err != nil {
  36. return nil, err
  37. } else if !isDir(repoPath) {
  38. return nil, errors.New("no such file or directory")
  39. }
  40. fs := osfs.New(repoPath)
  41. _, err = fs.Stat(".git")
  42. if err == nil {
  43. fs, err = fs.Chroot(".git")
  44. if err != nil {
  45. return nil, err
  46. }
  47. }
  48. // the "clone --shared" repo doesn't work well with go-git AlternativeFS, https://github.com/go-git/go-git/issues/1006
  49. // 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.
  50. var altFs billy.Filesystem
  51. if setting.IsWindows {
  52. altFs = osfs.New(filepath.VolumeName(setting.RepoRootPath) + "\\") // TODO: does it really work for Windows? Need some time to check.
  53. } else {
  54. altFs = osfs.New("/")
  55. }
  56. storage := filesystem.NewStorageWithOptions(fs, cache.NewObjectLRUDefault(), filesystem.Options{KeepDescriptors: true, LargeObjectThreshold: setting.Git.LargeObjectThreshold, AlternatesFS: altFs})
  57. gogitRepo, err := gogit.Open(storage, fs)
  58. if err != nil {
  59. return nil, err
  60. }
  61. return &Repository{
  62. Path: repoPath,
  63. gogitRepo: gogitRepo,
  64. gogitStorage: storage,
  65. tagCache: newObjectCache(),
  66. Ctx: ctx,
  67. }, nil
  68. }
  69. // Close this repository, in particular close the underlying gogitStorage if this is not nil
  70. func (repo *Repository) Close() (err error) {
  71. if repo == nil || repo.gogitStorage == nil {
  72. return
  73. }
  74. if err := repo.gogitStorage.Close(); err != nil {
  75. gitealog.Error("Error closing storage: %v", err)
  76. }
  77. repo.LastCommitCache = nil
  78. repo.tagCache = nil
  79. return
  80. }
  81. // GoGitRepo gets the go-git repo representation
  82. func (repo *Repository) GoGitRepo() *gogit.Repository {
  83. return repo.gogitRepo
  84. }