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