Merge pull request '[PERFORMANCE] git check-attr on bare repo if supported' (#2763) from oliverpool/forgejo:check_attr_bare into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2763 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
This commit is contained in:
commit
1684f0e5bf
17 changed files with 450 additions and 386 deletions
|
@ -7,6 +7,7 @@ package gitdiff
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"cmp"
|
||||
"context"
|
||||
"fmt"
|
||||
"html"
|
||||
|
@ -1172,38 +1173,32 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
|||
}
|
||||
diff.Start = opts.SkipTo
|
||||
|
||||
checker, deferable := gitRepo.CheckAttributeReader(opts.AfterCommitID)
|
||||
defer deferable()
|
||||
checker, err := gitRepo.GitAttributeChecker(opts.AfterCommitID, git.LinguistAttributes...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to GitAttributeChecker: %w", err)
|
||||
}
|
||||
defer checker.Close()
|
||||
|
||||
for _, diffFile := range diff.Files {
|
||||
|
||||
gotVendor := false
|
||||
gotGenerated := false
|
||||
if checker != nil {
|
||||
attrs, err := checker.CheckPath(diffFile.Name)
|
||||
if err == nil {
|
||||
if vendored, has := attrs["linguist-vendored"]; has {
|
||||
if vendored == "set" || vendored == "true" {
|
||||
diffFile.IsVendored = true
|
||||
gotVendor = true
|
||||
} else {
|
||||
gotVendor = vendored == "false"
|
||||
}
|
||||
}
|
||||
if generated, has := attrs["linguist-generated"]; has {
|
||||
if generated == "set" || generated == "true" {
|
||||
diffFile.IsGenerated = true
|
||||
gotGenerated = true
|
||||
} else {
|
||||
gotGenerated = generated == "false"
|
||||
}
|
||||
}
|
||||
if language, has := attrs["linguist-language"]; has && language != "unspecified" && language != "" {
|
||||
diffFile.Language = language
|
||||
} else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" {
|
||||
diffFile.Language = language
|
||||
}
|
||||
}
|
||||
|
||||
attrs, err := checker.CheckPath(diffFile.Name)
|
||||
if err != nil {
|
||||
log.Error("checker.CheckPath(%s) failed: %v", diffFile.Name, err)
|
||||
} else {
|
||||
vendored := attrs["linguist-vendored"].Bool()
|
||||
diffFile.IsVendored = vendored.Value()
|
||||
gotVendor = vendored.Has()
|
||||
|
||||
generated := attrs["linguist-generated"].Bool()
|
||||
diffFile.IsGenerated = generated.Value()
|
||||
gotGenerated = generated.Has()
|
||||
|
||||
diffFile.Language = cmp.Or(
|
||||
attrs["linguist-language"].String(),
|
||||
attrs["gitlab-language"].Prefix(),
|
||||
)
|
||||
}
|
||||
|
||||
if !gotVendor {
|
||||
|
|
|
@ -273,31 +273,6 @@ func GetBlobBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
|
|||
|
||||
// TryGetContentLanguage tries to get the (linguist) language of the file content
|
||||
func TryGetContentLanguage(gitRepo *git.Repository, commitID, treePath string) (string, error) {
|
||||
indexFilename, worktree, deleteTemporaryFile, err := gitRepo.ReadTreeToTemporaryIndex(commitID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer deleteTemporaryFile()
|
||||
|
||||
filename2attribute2info, err := gitRepo.CheckAttribute(git.CheckAttributeOpts{
|
||||
CachedOnly: true,
|
||||
Attributes: []string{"linguist-language", "gitlab-language"},
|
||||
Filenames: []string{treePath},
|
||||
IndexFile: indexFilename,
|
||||
WorkTree: worktree,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
language := filename2attribute2info[treePath]["linguist-language"]
|
||||
if language == "" || language == "unspecified" {
|
||||
language = filename2attribute2info[treePath]["gitlab-language"]
|
||||
}
|
||||
if language == "unspecified" {
|
||||
language = ""
|
||||
}
|
||||
|
||||
return language, nil
|
||||
attribute, err := gitRepo.GitAttributeFirst(commitID, treePath, "linguist-language", "gitlab-language")
|
||||
return attribute.Prefix(), err
|
||||
}
|
||||
|
|
|
@ -400,16 +400,12 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
|
|||
var lfsMetaObject *git_model.LFSMetaObject
|
||||
if setting.LFS.StartServer && hasOldBranch {
|
||||
// Check there is no way this can return multiple infos
|
||||
filename2attribute2info, err := t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
|
||||
Attributes: []string{"filter"},
|
||||
Filenames: []string{file.Options.treePath},
|
||||
CachedOnly: true,
|
||||
})
|
||||
filterAttribute, err := t.gitRepo.GitAttributeFirst("", file.Options.treePath, "filter")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if filename2attribute2info[file.Options.treePath] != nil && filename2attribute2info[file.Options.treePath]["filter"] == "lfs" {
|
||||
if filterAttribute == "lfs" {
|
||||
// OK so we are supposed to LFS this data!
|
||||
pointer, err := lfs.GeneratePointer(treeObjectContentReader)
|
||||
if err != nil {
|
||||
|
|
|
@ -105,23 +105,9 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
|||
}
|
||||
}
|
||||
|
||||
var filename2attribute2info map[string]map[string]string
|
||||
if setting.LFS.StartServer {
|
||||
filename2attribute2info, err = t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
|
||||
Attributes: []string{"filter"},
|
||||
Filenames: names,
|
||||
CachedOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Copy uploaded files into repository.
|
||||
for i := range infos {
|
||||
if err := copyUploadedLFSFileIntoRepository(&infos[i], filename2attribute2info, t, opts.TreePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := copyUploadedLFSFilesIntoRepository(infos, t, opts.TreePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now write the tree
|
||||
|
@ -169,7 +155,44 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
|||
return repo_model.DeleteUploads(ctx, uploads...)
|
||||
}
|
||||
|
||||
func copyUploadedLFSFileIntoRepository(info *uploadInfo, filename2attribute2info map[string]map[string]string, t *TemporaryUploadRepository, treePath string) error {
|
||||
func copyUploadedLFSFilesIntoRepository(infos []uploadInfo, t *TemporaryUploadRepository, treePath string) error {
|
||||
var storeInLFSFunc func(string) (bool, error)
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
checker, err := t.gitRepo.GitAttributeChecker("", "filter")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer checker.Close()
|
||||
|
||||
storeInLFSFunc = func(name string) (bool, error) {
|
||||
attrs, err := checker.CheckPath(name)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not CheckPath(%s): %w", name, err)
|
||||
}
|
||||
return attrs["filter"] == "lfs", nil
|
||||
}
|
||||
}
|
||||
|
||||
// Copy uploaded files into repository.
|
||||
for i, info := range infos {
|
||||
storeInLFS := false
|
||||
if storeInLFSFunc != nil {
|
||||
var err error
|
||||
storeInLFS, err = storeInLFSFunc(info.upload.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := copyUploadedLFSFileIntoRepository(&infos[i], storeInLFS, t, treePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyUploadedLFSFileIntoRepository(info *uploadInfo, storeInLFS bool, t *TemporaryUploadRepository, treePath string) error {
|
||||
file, err := os.Open(info.upload.LocalPath())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -177,7 +200,7 @@ func copyUploadedLFSFileIntoRepository(info *uploadInfo, filename2attribute2info
|
|||
defer file.Close()
|
||||
|
||||
var objectHash string
|
||||
if setting.LFS.StartServer && filename2attribute2info[info.upload.Name] != nil && filename2attribute2info[info.upload.Name]["filter"] == "lfs" {
|
||||
if storeInLFS {
|
||||
// Handle LFS
|
||||
// FIXME: Inefficient! this should probably happen in models.Upload
|
||||
pointer, err := lfs.GeneratePointer(file)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue