2020-12-17 19:30:47 +05:30
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 23:50:29 +05:30
// SPDX-License-Identifier: MIT
2020-12-17 19:30:47 +05:30
2021-08-24 22:17:09 +05:30
//go:build gogit
2020-12-17 19:30:47 +05:30
package git
import (
2021-12-01 01:36:32 +05:30
"context"
2020-12-17 19:30:47 +05:30
"errors"
"path/filepath"
gitealog "code.gitea.io/gitea/modules/log"
2021-07-01 02:28:45 +05:30
"code.gitea.io/gitea/modules/setting"
2024-01-23 11:10:00 +05:30
"github.com/go-git/go-billy/v5"
2020-12-17 19:30:47 +05:30
"github.com/go-git/go-billy/v5/osfs"
gogit "github.com/go-git/go-git/v5"
2023-12-14 02:32:00 +05:30
"github.com/go-git/go-git/v5/plumbing"
2020-12-17 19:30:47 +05:30
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/storage/filesystem"
)
2024-01-19 21:35:02 +05:30
func init ( ) {
isGogit = true
}
2020-12-17 19:30:47 +05:30
// Repository represents a Git repository.
type Repository struct {
Path string
tagCache * ObjectCache
gogitRepo * gogit . Repository
gogitStorage * filesystem . Storage
gpgSettings * GPGSettings
2021-12-01 01:36:32 +05:30
2022-07-25 21:09:42 +05:30
Ctx context . Context
LastCommitCache * LastCommitCache
2023-12-14 02:32:00 +05:30
objectFormat ObjectFormat
2020-12-17 19:30:47 +05:30
}
2022-03-30 00:43:41 +05:30
// openRepositoryWithDefaultContext opens the repository at the given path with DefaultContext.
func openRepositoryWithDefaultContext ( repoPath string ) ( * Repository , error ) {
return OpenRepository ( DefaultContext , repoPath )
2021-12-01 01:36:32 +05:30
}
2022-03-30 00:43:41 +05:30
// OpenRepository opens the repository at the given path within the context.Context
func OpenRepository ( ctx context . Context , repoPath string ) ( * Repository , error ) {
2020-12-17 19:30:47 +05:30
repoPath , err := filepath . Abs ( repoPath )
if err != nil {
return nil , err
} else if ! isDir ( repoPath ) {
return nil , errors . New ( "no such file or directory" )
}
fs := osfs . New ( repoPath )
_ , err = fs . Stat ( ".git" )
if err == nil {
fs , err = fs . Chroot ( ".git" )
if err != nil {
return nil , err
}
}
2024-01-23 11:10:00 +05:30
// the "clone --shared" repo doesn't work well with go-git AlternativeFS, https://github.com/go-git/go-git/issues/1006
// 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.
var altFs billy . Filesystem
if setting . IsWindows {
altFs = osfs . New ( filepath . VolumeName ( setting . RepoRootPath ) + "\\" ) // TODO: does it really work for Windows? Need some time to check.
} else {
altFs = osfs . New ( "/" )
}
storage := filesystem . NewStorageWithOptions ( fs , cache . NewObjectLRUDefault ( ) , filesystem . Options { KeepDescriptors : true , LargeObjectThreshold : setting . Git . LargeObjectThreshold , AlternatesFS : altFs } )
2020-12-17 19:30:47 +05:30
gogitRepo , err := gogit . Open ( storage , fs )
if err != nil {
return nil , err
}
return & Repository {
Path : repoPath ,
gogitRepo : gogitRepo ,
gogitStorage : storage ,
tagCache : newObjectCache ( ) ,
2021-12-01 01:36:32 +05:30
Ctx : ctx ,
2023-12-14 02:32:00 +05:30
objectFormat : ParseGogitHash ( plumbing . ZeroHash ) . Type ( ) ,
2020-12-17 19:30:47 +05:30
} , nil
}
// Close this repository, in particular close the underlying gogitStorage if this is not nil
2024-02-25 18:35:23 +05:30
func ( repo * Repository ) Close ( ) error {
2020-12-17 19:30:47 +05:30
if repo == nil || repo . gogitStorage == nil {
2024-02-25 18:35:23 +05:30
return nil
2020-12-17 19:30:47 +05:30
}
if err := repo . gogitStorage . Close ( ) ; err != nil {
gitealog . Error ( "Error closing storage: %v" , err )
}
2024-02-25 18:35:23 +05:30
repo . gogitStorage = nil
2022-07-25 21:09:42 +05:30
repo . LastCommitCache = nil
repo . tagCache = nil
2024-02-25 18:35:23 +05:30
return nil
2020-12-17 19:30:47 +05:30
}
// GoGitRepo gets the go-git repo representation
func ( repo * Repository ) GoGitRepo ( ) * gogit . Repository {
return repo . gogitRepo
}