mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-07 13:12:13 +00:00
deccd53c24
1. always use "last commit cache" 2. correctly build the cache key for any input (SafeCacheKey) 3. fix the git note "last commit cache FIXME" and avoid OOM
90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package git
|
|
|
|
import (
|
|
"context"
|
|
"path"
|
|
"strings"
|
|
|
|
"gitea.dev/modules/setting"
|
|
)
|
|
|
|
// NotesRef is the git ref where Gitea will look for git-notes data.
|
|
// The value ("refs/notes/commits") is the default ref used by git-notes.
|
|
const NotesRef = "refs/notes/commits"
|
|
|
|
// Note stores information about a note created using git-notes.
|
|
type Note struct {
|
|
refCommit *Commit
|
|
|
|
BlobMessage CommitMessage // if the blob is too large, the message will be truncated
|
|
BlobSize int64
|
|
TreePath string
|
|
}
|
|
|
|
// GetNote retrieves the git-notes data for a given commit.
|
|
func GetNote(ctx context.Context, repo *Repository, commitID string) (*Note, error) {
|
|
noteCommit, err := repo.GetCommit(ctx, NotesRef)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// A note for a commit is stored in a blob in the notes commit tree, with the path being the commit ID.
|
|
// The path can be "FullCommitID" or a fanout path like "ab/cdef...." or "ab/cd/ef.....".
|
|
tree := noteCommit.Tree()
|
|
entryName := commitID
|
|
var entry *TreeEntry
|
|
var treePathBuf strings.Builder
|
|
for len(entryName) > 2 {
|
|
entry, err = tree.GetTreeEntryByPath(ctx, repo, entryName)
|
|
if err == nil {
|
|
treePathBuf.WriteString(entryName)
|
|
break
|
|
} else if IsErrNotExist(err) {
|
|
fanoutDir, fanoutName := entryName[0:2], entryName[2:]
|
|
tree, err = tree.SubTree(ctx, repo, fanoutDir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
treePathBuf.WriteString(fanoutDir)
|
|
treePathBuf.WriteByte('/')
|
|
entryName = fanoutName
|
|
} else {
|
|
return nil, err
|
|
}
|
|
}
|
|
if entry == nil {
|
|
return nil, ErrNotExist{ID: commitID}
|
|
}
|
|
|
|
treePath := treePathBuf.String()
|
|
blob := entry.Blob(repo)
|
|
note := &Note{TreePath: treePath, refCommit: noteCommit}
|
|
note.BlobMessage.MessageRaw, err = blob.GetBlobContent(ctx, setting.UI.MaxDisplayFileSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
note.BlobSize = blob.Size(ctx) // it should be called after the get blob content, then the "size" is cached
|
|
return note, nil
|
|
}
|
|
|
|
func GetNoteWithLastCommit(ctx context.Context, repo *Repository, commitID string) (*Note, *Commit, error) {
|
|
note, err := GetNote(ctx, repo, commitID)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
parentPath, entryName := path.Split(note.TreePath)
|
|
parentPath = strings.Trim(parentPath, "/")
|
|
lastCommits, err := GetLastCommitForPaths(ctx, repo, note.refCommit, parentPath, []string{entryName})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
lastCommit := lastCommits[entryName]
|
|
if lastCommit == nil {
|
|
return nil, nil, ErrNotExist{ID: commitID}
|
|
}
|
|
return note, lastCommit, nil
|
|
}
|