diff --git a/modules/actions/scoped_workflows.go b/modules/actions/scoped_workflows.go index 0789015ac18..e2b4ceecfb1 100644 --- a/modules/actions/scoped_workflows.go +++ b/modules/actions/scoped_workflows.go @@ -4,6 +4,8 @@ package actions import ( + "context" + "gitea.dev/modules/actions/jobparser" "gitea.dev/modules/git" "gitea.dev/modules/log" @@ -13,8 +15,8 @@ import ( ) // ListScopedWorkflows lists scoped workflow files (under SCOPED_WORKFLOW_DIRS) at the given commit. -func ListScopedWorkflows(commit *git.Commit) (string, git.Entries, error) { - return listWorkflowsInDirs(commit, setting.Actions.ScopedWorkflowDirs) +func ListScopedWorkflows(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, git.Entries, error) { + return listWorkflowsInDirs(ctx, gitRepo, commit, setting.Actions.ScopedWorkflowDirs) } // ParsedScopedWorkflow is one scoped workflow's source-side parse result @@ -26,15 +28,15 @@ type ParsedScopedWorkflow struct { } // ParseScopedWorkflows lists and parses the scoped workflow files at sourceCommit (under SCOPED_WORKFLOW_DIRS). -func ParseScopedWorkflows(sourceCommit *git.Commit) ([]*ParsedScopedWorkflow, error) { - _, entries, err := ListScopedWorkflows(sourceCommit) +func ParseScopedWorkflows(ctx context.Context, gitRepo *git.Repository, sourceCommit *git.Commit) ([]*ParsedScopedWorkflow, error) { + _, entries, err := ListScopedWorkflows(ctx, gitRepo, sourceCommit) if err != nil { return nil, err } parsed := make([]*ParsedScopedWorkflow, 0, len(entries)) for _, entry := range entries { - content, err := GetContentFromEntry(entry) + content, err := GetContentFromEntry(gitRepo, entry) if err != nil { return nil, err } diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go index dc7c55b9c04..6414efc9dd9 100644 --- a/modules/actions/workflows.go +++ b/modules/actions/workflows.go @@ -5,6 +5,7 @@ package actions import ( "bytes" + "context" "fmt" "path" "slices" @@ -69,16 +70,16 @@ func isWorkflowInDirs(path string, dirs []string) bool { return false } -func ListWorkflows(commit *git.Commit) (string, git.Entries, error) { - return listWorkflowsInDirs(commit, setting.Actions.WorkflowDirs) +func ListWorkflows(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, git.Entries, error) { + return listWorkflowsInDirs(ctx, gitRepo, commit, setting.Actions.WorkflowDirs) } -func listWorkflowsInDirs(commit *git.Commit, dirs []string) (string, git.Entries, error) { +func listWorkflowsInDirs(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, dirs []string) (string, git.Entries, error) { var tree *git.Tree var err error var workflowDir string for _, workflowDir = range dirs { - tree, err = commit.SubTree(workflowDir) + tree, err = commit.SubTree(ctx, gitRepo, workflowDir) if err == nil { break } @@ -90,7 +91,7 @@ func listWorkflowsInDirs(commit *git.Commit, dirs []string) (string, git.Entries return "", nil, nil } - entries, err := tree.ListEntriesRecursiveFast() + entries, err := tree.ListEntriesRecursiveFast(ctx, gitRepo) if err != nil { return "", nil, err } @@ -104,8 +105,8 @@ func listWorkflowsInDirs(commit *git.Commit, dirs []string) (string, git.Entries return workflowDir, ret, nil } -func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) { - f, err := entry.Blob().DataAsync() +func GetContentFromEntry(gitRepo *git.Repository, entry *git.TreeEntry) ([]byte, error) { + f, err := entry.Blob(gitRepo).DataAsync() if err != nil { return nil, err } @@ -175,19 +176,20 @@ func ShouldEventCreateCommitStatus(event string) bool { } func DetectWorkflows( + ctx context.Context, gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, detectSchedule bool, ) (workflows, schedules, filtered []*DetectedWorkflow, err error) { - _, entries, err := ListWorkflows(commit) + _, entries, err := ListWorkflows(ctx, gitRepo, commit) if err != nil { return nil, nil, nil, err } for _, entry := range entries { - content, err := GetContentFromEntry(entry) + content, err := GetContentFromEntry(gitRepo, entry) if err != nil { return nil, nil, nil, err } @@ -229,15 +231,15 @@ func DetectWorkflows( return workflows, schedules, filtered, nil } -func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) { - _, entries, err := ListWorkflows(commit) +func DetectScheduledWorkflows(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) { + _, entries, err := ListWorkflows(ctx, gitRepo, commit) if err != nil { return nil, err } wfs := make([]*DetectedWorkflow, 0, len(entries)) for _, entry := range entries { - content, err := GetContentFromEntry(entry) + content, err := GetContentFromEntry(gitRepo, entry) if err != nil { return nil, err } @@ -284,7 +286,7 @@ func detectWorkflowMatch(gitRepo *git.Repository, commit *git.Commit, triggedEve case // push webhook_module.HookEventPush: - return matchPushEvent(commit, payload.(*api.PushPayload), evt) + return matchPushEvent(gitRepo, commit, payload.(*api.PushPayload), evt) case // issues webhook_module.HookEventIssues, @@ -357,7 +359,7 @@ func detectWorkflowMatch(gitRepo *git.Repository, commit *git.Commit, triggedEve } } -func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) detectResult { +func matchPushEvent(gitRepo *git.Repository, commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) detectResult { // with no special filter parameters if len(evt.Acts()) == 0 { return detectMatched @@ -423,7 +425,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa matchTimes++ break } - filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) + filesChanged, err := commit.GetFilesChangedSinceCommit(gitRepo, pushPayload.Before) if err != nil { log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) return detectNotApplicable @@ -440,7 +442,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa matchTimes++ break } - filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) + filesChanged, err := commit.GetFilesChangedSinceCommit(gitRepo, pushPayload.Before) if err != nil { log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) return detectNotApplicable @@ -590,7 +592,7 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa matchTimes++ } case "paths": - filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.MergeBase) + filesChanged, err := headCommit.GetFilesChangedSinceCommit(gitRepo, prPayload.PullRequest.MergeBase) if err != nil { log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err) return detectNotApplicable @@ -603,7 +605,7 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa matchTimes++ } case "paths-ignore": - filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.MergeBase) + filesChanged, err := headCommit.GetFilesChangedSinceCommit(gitRepo, prPayload.PullRequest.MergeBase) if err != nil { log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err) return detectNotApplicable diff --git a/modules/fileicon/entry.go b/modules/fileicon/entry.go index 2f76da24758..1174600da76 100644 --- a/modules/fileicon/entry.go +++ b/modules/fileicon/entry.go @@ -3,7 +3,11 @@ package fileicon -import "gitea.dev/modules/git" +import ( + "context" + + "gitea.dev/modules/git" +) type EntryInfo struct { BaseName string @@ -12,10 +16,10 @@ type EntryInfo struct { IsOpen bool } -func EntryInfoFromGitTreeEntry(commit *git.Commit, fullPath string, gitEntry *git.TreeEntry) *EntryInfo { +func EntryInfoFromGitTreeEntry(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, fullPath string, gitEntry *git.TreeEntry) *EntryInfo { ret := &EntryInfo{BaseName: gitEntry.Name(), EntryMode: gitEntry.Mode()} if gitEntry.IsLink() { - if res, err := git.EntryFollowLink(commit, fullPath, gitEntry); err == nil && res.TargetEntry.IsDir() { + if res, err := git.EntryFollowLink(ctx, gitRepo, commit, fullPath, gitEntry); err == nil && res.TargetEntry.IsDir() { ret.SymlinkToMode = res.TargetEntry.Mode() } } diff --git a/modules/git/commit.go b/modules/git/commit.go index 9600ec1b6ae..d43bd6800a4 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -17,17 +17,17 @@ import ( // Commit represents a git commit. type Commit struct { - Tree // FIXME: bad design, this field can be nil if the commit is from "last commit cache" - CommitMessage ID ObjectID + TreeID ObjectID + Parents []ObjectID Author *Signature // never nil Committer *Signature // never nil Signature *CommitSignature - Parents []ObjectID // ID strings submoduleCache *ObjectCache[*SubModule] + treeCache *Tree } // CommitSignature represents a git commit signature part. @@ -46,12 +46,12 @@ func (c *Commit) ParentID(n int) (ObjectID, error) { } // Parent returns n-th parent (0-based index) of the commit. -func (c *Commit) Parent(n int) (*Commit, error) { +func (c *Commit) Parent(gitRepo *Repository, n int) (*Commit, error) { id, err := c.ParentID(n) if err != nil { return nil, err } - parent, err := c.repo.getCommit(id) + parent, err := gitRepo.getCommit(id) if err != nil { return nil, err } @@ -65,25 +65,44 @@ func (c *Commit) ParentCount() int { } // GetCommitByPath return the commit of relative path object. -func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) { - if c.repo.LastCommitCache != nil { - return c.repo.LastCommitCache.GetCommitByPath(c.ID.String(), relpath) +func (c *Commit) GetCommitByPath(gitRepo *Repository, relpath string) (*Commit, error) { + if gitRepo.LastCommitCache != nil { + return gitRepo.LastCommitCache.GetCommitByPath(c.ID.String(), relpath) } - return c.repo.getCommitByPathWithID(c.ID, relpath) + return gitRepo.getCommitByPathWithID(c.ID, relpath) +} + +func (c *Commit) Tree() *Tree { + if c.treeCache == nil { + c.treeCache = newTree(c.TreeID) + } + return c.treeCache +} + +func (c *Commit) GetBlobByPath(ctx context.Context, gitRepo *Repository, relpath string) (*Blob, error) { + return c.Tree().GetBlobByPath(ctx, gitRepo, relpath) +} + +func (c *Commit) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relpath string) (_ *TreeEntry, err error) { + return c.Tree().GetTreeEntryByPath(ctx, gitRepo, relpath) +} + +func (c *Commit) SubTree(ctx context.Context, gitRepo *Repository, relpath string) (*Tree, error) { + return c.Tree().SubTree(ctx, gitRepo, relpath) } // CommitsByRange returns the specific page commits before current revision, every page's number default by CommitsRangeSize -func (c *Commit) CommitsByRange(page, pageSize int, not, since, until string) ([]*Commit, error) { - return c.repo.commitsByRangeWithTime(c.ID, page, pageSize, not, since, until) +func (c *Commit) CommitsByRange(gitRepo *Repository, page, pageSize int, not, since, until string) ([]*Commit, error) { + return gitRepo.commitsByRangeWithTime(c.ID, page, pageSize, not, since, until) } // CommitsBefore returns all the commits before current revision -func (c *Commit) CommitsBefore() ([]*Commit, error) { - return c.repo.getCommitsBefore(c.ID) +func (c *Commit) CommitsBefore(gitRepo *Repository) ([]*Commit, error) { + return gitRepo.getCommitsBefore(c.ID) } // HasPreviousCommit returns true if a given commitHash is contained in commit's parents -func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) { +func (c *Commit) HasPreviousCommit(ctx context.Context, gitRepo *Repository, objectID ObjectID) (bool, error) { this := c.ID.String() that := objectID.String() @@ -93,8 +112,8 @@ func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) { _, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor"). AddDynamicArguments(that, this). - WithDir(c.repo.Path). - RunStdString(c.repo.Ctx) + WithDir(gitRepo.Path). + RunStdString(ctx) if err == nil { return true, nil } @@ -108,8 +127,8 @@ func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) { } // IsForcePush returns true if a push from oldCommitHash to this is a force push -func (c *Commit) IsForcePush(oldCommitID string) (bool, error) { - objectFormat, err := c.repo.GetObjectFormat() +func (c *Commit) IsForcePush(ctx context.Context, gitRepo *Repository, oldCommitID string) (bool, error) { + objectFormat, err := gitRepo.GetObjectFormat() if err != nil { return false, err } @@ -117,22 +136,22 @@ func (c *Commit) IsForcePush(oldCommitID string) (bool, error) { return false, nil } - oldCommit, err := c.repo.GetCommit(oldCommitID) + oldCommit, err := gitRepo.GetCommit(oldCommitID) if err != nil { return false, err } - hasPreviousCommit, err := c.HasPreviousCommit(oldCommit.ID) + hasPreviousCommit, err := c.HasPreviousCommit(ctx, gitRepo, oldCommit.ID) return !hasPreviousCommit, err } // CommitsBeforeLimit returns num commits before current revision -func (c *Commit) CommitsBeforeLimit(num int) ([]*Commit, error) { - return c.repo.getCommitsBeforeLimit(c.ID, num) +func (c *Commit) CommitsBeforeLimit(gitRepo *Repository, num int) ([]*Commit, error) { + return gitRepo.getCommitsBeforeLimit(c.ID, num) } // CommitsBeforeUntil returns the commits in range "[cur, ref)" -func (c *Commit) CommitsBeforeUntil(ref RefName) ([]*Commit, error) { - return c.repo.CommitsBetween(c.ID.RefName(), ref, -1) +func (c *Commit) CommitsBeforeUntil(gitRepo *Repository, ref RefName) ([]*Commit, error) { + return gitRepo.CommitsBetween(c.ID.RefName(), ref, -1) } // SearchCommitsOptions specify the parameters for SearchCommits @@ -175,39 +194,29 @@ func NewSearchCommitsOptions(searchString string, forAllRefs bool) SearchCommits } // SearchCommits returns the commits match the keyword before current revision -func (c *Commit) SearchCommits(opts SearchCommitsOptions) ([]*Commit, error) { - return c.repo.searchCommits(c.ID, opts) +func (c *Commit) SearchCommits(gitRepo *Repository, opts SearchCommitsOptions) ([]*Commit, error) { + return gitRepo.searchCommits(c.ID, opts) } // GetFilesChangedSinceCommit get all changed file names between pastCommit to current revision -func (c *Commit) GetFilesChangedSinceCommit(pastCommit string) ([]string, error) { - return c.repo.GetFilesChangedBetween(pastCommit, c.ID.String()) +func (c *Commit) GetFilesChangedSinceCommit(gitRepo *Repository, pastCommit string) ([]string, error) { + return gitRepo.GetFilesChangedBetween(pastCommit, c.ID.String()) } // FileChangedSinceCommit Returns true if the file given has changed since the past commit // YOU MUST ENSURE THAT pastCommit is a valid commit ID. -func (c *Commit) FileChangedSinceCommit(filename, pastCommit string) (bool, error) { - return c.repo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String()) -} - -// HasFile returns true if the file given exists on this commit -// This does only mean it's there - it does not mean the file was changed during the commit. -func (c *Commit) HasFile(filename string) (bool, error) { - _, err := c.GetBlobByPath(filename) - if err != nil { - return false, err - } - return true, nil +func (c *Commit) FileChangedSinceCommit(gitRepo *Repository, filename, pastCommit string) (bool, error) { + return gitRepo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String()) } // GetFileContent reads a file content as a string or returns false if this was not possible -func (c *Commit) GetFileContent(filename string, limit int) (string, error) { - entry, err := c.GetTreeEntryByPath(filename) +func (c *Commit) GetFileContent(ctx context.Context, gitRepo *Repository, filename string, limit int) (string, error) { + entry, err := c.GetTreeEntryByPath(ctx, gitRepo, filename) if err != nil { return "", err } - r, err := entry.Blob().DataAsync() + r, err := entry.Blob(gitRepo).DataAsync() if err != nil { return "", err } diff --git a/modules/git/commit_info.go b/modules/git/commit_info.go index 4f76a28f31c..87a6ddd8d15 100644 --- a/modules/git/commit_info.go +++ b/modules/git/commit_info.go @@ -3,6 +3,8 @@ package git +import "context" + // CommitInfo describes the first commit with the provided entry type CommitInfo struct { Entry *TreeEntry @@ -10,8 +12,8 @@ type CommitInfo struct { SubmoduleFile *CommitSubmoduleFile } -func GetCommitInfoSubmoduleFile(repoLink, fullPath string, commit *Commit, refCommitID ObjectID) (*CommitSubmoduleFile, error) { - submodule, err := commit.GetSubModule(fullPath) +func GetCommitInfoSubmoduleFile(ctx context.Context, repoLink, fullPath string, gitRepo *Repository, commit *Commit, refCommitID ObjectID) (*CommitSubmoduleFile, error) { + submodule, err := commit.GetSubModule(ctx, gitRepo, fullPath) if err != nil { return nil, err } diff --git a/modules/git/commit_info_gogit.go b/modules/git/commit_info_gogit.go index 6174f46f07f..6922cb92ff5 100644 --- a/modules/git/commit_info_gogit.go +++ b/modules/git/commit_info_gogit.go @@ -17,7 +17,7 @@ import ( ) // GetCommitsInfo gets information of all commits that are corresponding to these entries -func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) { +func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo *Repository, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) { entryPaths := make([]string, len(tes)+1) // Get the commit for the treePath itself entryPaths[0] = "" @@ -25,25 +25,16 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * entryPaths[i+1] = entry.Name() } - commitNodeIndex, commitGraphFile := commit.repo.CommitNodeIndex() - if commitGraphFile != nil { - defer commitGraphFile.Close() - } - - c, err := commitNodeIndex.Get(plumbing.Hash(commit.ID.RawValue())) - if err != nil { - return nil, nil, err - } - var revs map[string]*Commit - if commit.repo.LastCommitCache != nil { + var err error + if gitRepo.LastCommitCache != nil { var unHitPaths []string - revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache) + revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, gitRepo.LastCommitCache) if err != nil { return nil, nil, err } if len(unHitPaths) > 0 { - revs2, err := GetLastCommitForPaths(ctx, commit.repo.LastCommitCache, c, treePath, unHitPaths) + revs2, err := GetLastCommitForPaths(ctx, gitRepo, commit, treePath, unHitPaths) if err != nil { return nil, nil, err } @@ -51,13 +42,13 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * maps.Copy(revs, revs2) } } else { - revs, err = GetLastCommitForPaths(ctx, nil, c, treePath, entryPaths) + revs, err = GetLastCommitForPaths(ctx, gitRepo, commit, treePath, entryPaths) } if err != nil { return nil, nil, err } - commit.repo.gogitStorage.Close() + gitRepo.gogitStorage.Close() commitsInfo := make([]CommitInfo, len(tes)) for i, entry := range tes { @@ -72,7 +63,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * // If the entry is a submodule, add a submodule file for this if entry.IsSubModule() { - commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(repoLink, path.Join(treePath, entry.Name()), commit, entry.ID) + commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(ctx, repoLink, path.Join(treePath, entry.Name()), gitRepo, commit, entry.ID) if err != nil { return nil, nil, err } @@ -83,11 +74,10 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * // get it for free during the tree traversal and it's used for listing // pages to display information about newest commit for a given path. var treeCommit *Commit - var ok bool if treePath == "" { treeCommit = commit - } else if treeCommit, ok = revs[""]; ok { - treeCommit.repo = commit.repo + } else { + treeCommit = revs[""] } return commitsInfo, treeCommit, nil } @@ -162,7 +152,20 @@ func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cac } // GetLastCommitForPaths returns last commit information -func GetLastCommitForPaths(ctx context.Context, cache *LastCommitCache, c cgobject.CommitNode, treePath string, paths []string) (map[string]*Commit, error) { +func GetLastCommitForPaths(ctx context.Context, gitRepo *Repository, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) { + commitNodeIndex, commitGraphFile := gitRepo.CommitNodeIndex() + if commitGraphFile != nil { + defer commitGraphFile.Close() + } + + c, err := commitNodeIndex.Get(plumbing.Hash(commit.ID.RawValue())) + if err != nil { + return nil, err + } + return getLastCommitForPathsByCommitNode(ctx, gitRepo, c, treePath, paths) +} + +func getLastCommitForPathsByCommitNode(ctx context.Context, gitRepo *Repository, c cgobject.CommitNode, treePath string, paths []string) (map[string]*Commit, error) { refSha := c.ID().String() // We do a tree traversal with nodes sorted by commit time @@ -243,7 +246,7 @@ heaploop: // match any of the hashes being merged. This is more common for directories, // but it can also happen if a file is changed through conflict resolution. resultNodes[pth] = current.commit - if err := cache.Put(refSha, path.Join(treePath, pth), current.commit.ID().String()); err != nil { + if err := gitRepo.LastCommitCache.Put(refSha, path.Join(treePath, pth), current.commit.ID().String()); err != nil { return nil, err } } diff --git a/modules/git/commit_info_nogogit.go b/modules/git/commit_info_nogogit.go index a7125d23baf..9141d993410 100644 --- a/modules/git/commit_info_nogogit.go +++ b/modules/git/commit_info_nogogit.go @@ -15,7 +15,7 @@ import ( ) // GetCommitsInfo gets information of all commits that are corresponding to these entries -func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) { +func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo *Repository, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) { entryPaths := make([]string, len(tes)+1) // Get the commit for the treePath itself entryPaths[0] = "" @@ -26,15 +26,15 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * var err error var revs map[string]*Commit - if commit.repo.LastCommitCache != nil { + if gitRepo.LastCommitCache != nil { var unHitPaths []string - revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache) + revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, gitRepo.LastCommitCache) if err != nil { return nil, nil, err } if len(unHitPaths) > 0 { sort.Strings(unHitPaths) - commits, err := GetLastCommitForPaths(ctx, commit, treePath, unHitPaths) + commits, err := GetLastCommitForPaths(ctx, gitRepo, commit, treePath, unHitPaths) if err != nil { return nil, nil, err } @@ -43,7 +43,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * } } else { sort.Strings(entryPaths) - revs, err = GetLastCommitForPaths(ctx, commit, treePath, entryPaths) + revs, err = GetLastCommitForPaths(ctx, gitRepo, commit, treePath, entryPaths) } if err != nil { return nil, nil, err @@ -64,7 +64,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * // If the entry is a submodule, add a submodule file for this if entry.IsSubModule() { - commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(repoLink, path.Join(treePath, entry.Name()), commit, entry.ID) + commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(ctx, repoLink, path.Join(treePath, entry.Name()), gitRepo, commit, entry.ID) if err != nil { return nil, nil, err } @@ -75,11 +75,10 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit * // get it for free during the tree traversal, and it's used for listing // pages to display information about the newest commit for a given path. var treeCommit *Commit - var ok bool if treePath == "" { treeCommit = commit - } else if treeCommit, ok = revs[""]; ok { - treeCommit.repo = commit.repo + } else { + treeCommit = revs[""] } return commitsInfo, treeCommit, nil } @@ -104,9 +103,9 @@ func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cac } // GetLastCommitForPaths returns last commit information -func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) { +func GetLastCommitForPaths(ctx context.Context, gitRepo *Repository, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) { // We read backwards from the commit to obtain all of the commits - revs, err := walkGitLog(ctx, commit.repo, commit, treePath, paths...) + revs, err := walkGitLog(ctx, gitRepo, commit, treePath, paths...) if err != nil { return nil, err } @@ -126,7 +125,7 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string, continue } - c, err := commit.repo.GetCommit(commitID) // Ensure the commit exists in the repository + c, err := gitRepo.GetCommit(commitID) // Ensure the commit exists in the repository if err != nil { return nil, err } diff --git a/modules/git/commit_info_nogogit_test.go b/modules/git/commit_info_nogogit_test.go index 268130d3a76..278c7c1b37e 100644 --- a/modules/git/commit_info_nogogit_test.go +++ b/modules/git/commit_info_nogogit_test.go @@ -24,7 +24,7 @@ func TestEntries_GetCommitsInfo_ContextErr(t *testing.T) { commit, err := repo.GetCommit("feaf4ba6bc635fec442f46ddd4512416ec43c2c2") require.NoError(t, err) - entries, err := commit.Tree.ListEntries() + entries, err := commit.Tree().ListEntries(t.Context(), repo) require.NoError(t, err) countCommitInfosCommit := func(infos []CommitInfo) (nilCommits, nonNilCommits int) { @@ -39,14 +39,14 @@ func TestEntries_GetCommitsInfo_ContextErr(t *testing.T) { defer test.MockVariableValue(&walkGitLogDebugBeforeNext)() walkGitLogDebugBeforeNext = cancel - commitInfos, _, err := entries.GetCommitsInfo(ctx, "/any/repo-link", commit, "") + commitInfos, _, err := entries.GetCommitsInfo(ctx, "/any/repo-link", repo, commit, "") assert.NoError(t, err) nilCommits, nonNilCommits := countCommitInfosCommit(commitInfos) assert.Equal(t, 0, nonNilCommits) // no commit info due to canceled (or deadline-exceeded) context assert.Equal(t, 3, nilCommits) walkGitLogDebugBeforeNext = nil - commitInfos, _, err = entries.GetCommitsInfo(t.Context(), "/any/repo-link", commit, "") + commitInfos, _, err = entries.GetCommitsInfo(t.Context(), "/any/repo-link", repo, commit, "") assert.NoError(t, err) nilCommits, nonNilCommits = countCommitInfosCommit(commitInfos) assert.Equal(t, 3, nonNilCommits) diff --git a/modules/git/commit_info_test.go b/modules/git/commit_info_test.go index 1e1697b0066..97d27932b58 100644 --- a/modules/git/commit_info_test.go +++ b/modules/git/commit_info_test.go @@ -91,10 +91,9 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) { continue } assert.NotNil(t, commit) - assert.NotNil(t, commit.Tree) - assert.NotNil(t, commit.Tree.repo) + assert.NotNil(t, commit.TreeID) - tree, err := commit.Tree.SubTree(testCase.Path) + tree, err := commit.SubTree(t.Context(), repo1, testCase.Path) if err != nil { assert.NoError(t, err, "Unable to get subtree: %s of commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err) // no point trying to do anything else for this test. @@ -102,9 +101,8 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) { } assert.NotNil(t, tree, "tree is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path) - assert.NotNil(t, tree.repo, "repo is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path) - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(t.Context(), repo1) if err != nil { assert.NoError(t, err, "Unable to get entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err) // no point trying to do anything else for this test. @@ -112,7 +110,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) { } // FIXME: Context.TODO() - if graceful has started we should use its Shutdown context otherwise use install signals in TestMain. - commitsInfo, treeCommit, err := entries.GetCommitsInfo(t.Context(), "/any/repo-link", commit, testCase.Path) + commitsInfo, treeCommit, err := entries.GetCommitsInfo(t.Context(), "/any/repo-link", repo1, commit, testCase.Path) assert.NoError(t, err, "Unable to get commit information for entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err) if err != nil { t.FailNow() @@ -127,7 +125,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) { continue } assert.Equal(t, expectedInfo.CommitID, commit.ID.String()) - assert.Equal(t, expectedInfo.Size, entry.Size(), entry.Name()) + assert.Equal(t, expectedInfo.Size, entry.GetSize(t.Context(), repo1), entry.Name()) } } } @@ -155,9 +153,9 @@ func TestEntries_GetCommitsInfo(t *testing.T) { t.Run("NonExistingSubmoduleAsNil", func(t *testing.T) { commit, err := bareRepo1.GetCommit("HEAD") require.NoError(t, err) - treeEntry, err := commit.GetTreeEntryByPath("file1.txt") + treeEntry, err := commit.GetTreeEntryByPath(t.Context(), bareRepo1, "file1.txt") require.NoError(t, err) - cisf, err := GetCommitInfoSubmoduleFile("/any/repo-link", "file1.txt", commit, treeEntry.ID) + cisf, err := GetCommitInfoSubmoduleFile(t.Context(), "/any/repo-link", "file1.txt", bareRepo1, commit, treeEntry.ID) require.NoError(t, err) assert.Equal(t, &CommitSubmoduleFile{ repoLink: "/any/repo-link", @@ -169,52 +167,3 @@ func TestEntries_GetCommitsInfo(t *testing.T) { assert.Nil(t, cisf.SubmoduleWebLinkTree(t.Context())) }) } - -func BenchmarkEntries_GetCommitsInfo(b *testing.B) { - type benchmarkType struct { - url string - name string - } - - benchmarks := []benchmarkType{ - {url: "https://github.com/go-gitea/gitea.git", name: "gitea"}, - {url: "https://github.com/ethantkoenig/manyfiles.git", name: "manyfiles"}, - {url: "https://github.com/moby/moby.git", name: "moby"}, - {url: "https://github.com/golang/go.git", name: "go"}, - {url: "https://github.com/torvalds/linux.git", name: "linux"}, - } - - doBenchmark := func(benchmark benchmarkType) { - var commit *Commit - var entries Entries - var repo *Repository - repoPath, err := cloneRepo(b, benchmark.url) - if err != nil { - b.Fatal(err) - } - - if repo, err = OpenRepository(b.Context(), repoPath); err != nil { - b.Fatal(err) - } - defer repo.Close() - - if commit, err = repo.GetBranchCommit("master"); err != nil { - b.Fatal(err) - } else if entries, err = commit.Tree.ListEntries(); err != nil { - b.Fatal(err) - } - b.ResetTimer() - b.Run(benchmark.name, func(b *testing.B) { - for b.Loop() { - _, _, err := entries.GetCommitsInfo(b.Context(), "/any/repo-link", commit, "") - if err != nil { - b.Fatal(err) - } - } - }) - } - - for _, benchmark := range benchmarks { - doBenchmark(benchmark) - } -} diff --git a/modules/git/commit_reader.go b/modules/git/commit_reader.go index ce48d6f3198..350f93c74ad 100644 --- a/modules/git/commit_reader.go +++ b/modules/git/commit_reader.go @@ -15,7 +15,7 @@ const ( commitHeaderGpgsigSha256 = "gpgsig-sha256" ) -func assignCommitFields(gitRepo *Repository, commit *Commit, headerKey string, headerValue []byte) error { +func assignCommitFields(commit *Commit, headerKey string, headerValue []byte) error { if len(headerValue) > 0 && headerValue[len(headerValue)-1] == '\n' { headerValue = headerValue[:len(headerValue)-1] // remove trailing newline } @@ -25,7 +25,7 @@ func assignCommitFields(gitRepo *Repository, commit *Commit, headerKey string, h if err != nil { return fmt.Errorf("invalid tree ID %q: %w", string(headerValue), err) } - commit.Tree = *NewTree(gitRepo, objID) + commit.TreeID = objID case "parent": objID, err := NewIDFromString(string(headerValue)) if err != nil { @@ -48,7 +48,7 @@ func assignCommitFields(gitRepo *Repository, commit *Commit, headerKey string, h // We need this to interpret commits from cat-file or cat-file --batch // // If used as part of a cat-file --batch stream you need to limit the reader to the correct size -func CommitFromReader(gitRepo *Repository, objectID ObjectID, reader io.Reader) (*Commit, error) { +func CommitFromReader(objectID ObjectID, reader io.Reader) (*Commit, error) { commit := &Commit{ ID: objectID, Author: &Signature{}, @@ -74,7 +74,7 @@ func CommitFromReader(gitRepo *Repository, objectID ObjectID, reader io.Reader) k, v, _ := bytes.Cut(line, []byte{' '}) if len(k) != 0 || !inHeader { if headerKey != "" { - if err = assignCommitFields(gitRepo, commit, headerKey, headerValue); err != nil { + if err = assignCommitFields(commit, headerKey, headerValue); err != nil { return nil, fmt.Errorf("unable to parse commit %q: %w", objectID.String(), err) } } diff --git a/modules/git/commit_sha256_test.go b/modules/git/commit_sha256_test.go index 9fb1539dc99..b4975aa4257 100644 --- a/modules/git/commit_sha256_test.go +++ b/modules/git/commit_sha256_test.go @@ -65,7 +65,7 @@ signed commit` assert.NotNil(t, gitRepo) defer gitRepo.Close() - commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString)) + commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString)) assert.NoError(t, err) require.NotNil(t, commitFromReader) assert.EqualValues(t, sha, commitFromReader.ID) @@ -93,7 +93,7 @@ committer Adam Majer 1698676906 +0100 signed commit`, commitFromReader.Signature.Payload) assert.Equal(t, "Adam Majer ", commitFromReader.Author.String()) - commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n")) + commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n")) assert.NoError(t, err) commitFromReader.CommitMessage.MessageRaw += "\n\n" commitFromReader.Signature.Payload += "\n\n" @@ -118,15 +118,15 @@ func TestHasPreviousCommitSha256(t *testing.T) { assert.Equal(t, objectFormat, parentSHA.Type()) assert.Equal(t, "sha256", objectFormat.Name()) - haz, err := commit.HasPreviousCommit(parentSHA) + haz, err := commit.HasPreviousCommit(t.Context(), repo, parentSHA) assert.NoError(t, err) assert.True(t, haz) - hazNot, err := commit.HasPreviousCommit(notParentSHA) + hazNot, err := commit.HasPreviousCommit(t.Context(), repo, notParentSHA) assert.NoError(t, err) assert.False(t, hazNot) - selfNot, err := commit.HasPreviousCommit(commit.ID) + selfNot, err := commit.HasPreviousCommit(t.Context(), repo, commit.ID) assert.NoError(t, err) assert.False(t, selfNot) } diff --git a/modules/git/commit_submodule.go b/modules/git/commit_submodule.go index 5e5f90c20e5..d8103f46d4f 100644 --- a/modules/git/commit_submodule.go +++ b/modules/git/commit_submodule.go @@ -3,17 +3,19 @@ package git +import "context" + type SubmoduleWebLink struct { RepoWebLink, CommitWebLink string } // GetSubModules get all the submodules of current revision git tree -func (c *Commit) GetSubModules() (*ObjectCache[*SubModule], error) { +func (c *Commit) GetSubModules(ctx context.Context, gitRepo *Repository) (*ObjectCache[*SubModule], error) { if c.submoduleCache != nil { return c.submoduleCache, nil } - entry, err := c.GetTreeEntryByPath(".gitmodules") + entry, err := c.GetTreeEntryByPath(ctx, gitRepo, ".gitmodules") if err != nil { if _, ok := err.(ErrNotExist); ok { return nil, nil //nolint:nilnil // return nil to indicate that the submodule does not exist @@ -21,7 +23,7 @@ func (c *Commit) GetSubModules() (*ObjectCache[*SubModule], error) { return nil, err } - rd, err := entry.Blob().DataAsync() + rd, err := entry.Blob(gitRepo).DataAsync() if err != nil { return nil, err } @@ -37,8 +39,8 @@ func (c *Commit) GetSubModules() (*ObjectCache[*SubModule], error) { // GetSubModule gets the submodule by the entry name. // It returns "nil, nil" if the submodule does not exist, caller should always remember to check the "nil" -func (c *Commit) GetSubModule(entryName string) (*SubModule, error) { - modules, err := c.GetSubModules() +func (c *Commit) GetSubModule(ctx context.Context, gitRepo *Repository, entryName string) (*SubModule, error) { + modules, err := c.GetSubModules(ctx, gitRepo) if err != nil { return nil, err } diff --git a/modules/git/commit_test.go b/modules/git/commit_test.go index 53c4b46e8ea..8ec641909b9 100644 --- a/modules/git/commit_test.go +++ b/modules/git/commit_test.go @@ -61,7 +61,7 @@ empty commit` assert.NotNil(t, gitRepo) defer gitRepo.Close() - commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString)) + commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString)) assert.NoError(t, err) require.NotNil(t, commitFromReader) assert.EqualValues(t, sha, commitFromReader.ID) @@ -89,7 +89,7 @@ committer silverwind 1563741793 +0200 empty commit`, commitFromReader.Signature.Payload) assert.Equal(t, "silverwind ", commitFromReader.Author.String()) - commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n")) + commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n")) assert.NoError(t, err) commitFromReader.CommitMessage.MessageRaw += "\n\n" commitFromReader.Signature.Payload += "\n\n" @@ -125,7 +125,7 @@ ISO-8859-1` assert.NotNil(t, gitRepo) defer gitRepo.Close() - commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString)) + commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString)) assert.NoError(t, err) require.NotNil(t, commitFromReader) assert.EqualValues(t, sha, commitFromReader.ID) @@ -152,7 +152,7 @@ encoding ISO-8859-1 ISO-8859-1`, commitFromReader.Signature.Payload) assert.Equal(t, "KN4CK3R ", commitFromReader.Author.String()) - commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n")) + commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n")) assert.NoError(t, err) commitFromReader.CommitMessage.MessageRaw += "\n\n" commitFromReader.Signature.Payload += "\n\n" @@ -172,15 +172,15 @@ func TestHasPreviousCommit(t *testing.T) { parentSHA := MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2") notParentSHA := MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3") - haz, err := commit.HasPreviousCommit(parentSHA) + haz, err := commit.HasPreviousCommit(t.Context(), repo, parentSHA) assert.NoError(t, err) assert.True(t, haz) - hazNot, err := commit.HasPreviousCommit(notParentSHA) + hazNot, err := commit.HasPreviousCommit(t.Context(), repo, notParentSHA) assert.NoError(t, err) assert.False(t, hazNot) - selfNot, err := commit.HasPreviousCommit(commit.ID) + selfNot, err := commit.HasPreviousCommit(t.Context(), repo, commit.ID) assert.NoError(t, err) assert.False(t, selfNot) } diff --git a/modules/git/diff.go b/modules/git/diff.go index eebb3c098fe..1077c102e70 100644 --- a/modules/git/diff.go +++ b/modules/git/diff.go @@ -75,7 +75,7 @@ func getRepoRawDiffForFileCmd(_ context.Context, repo *Repository, startCommit, } else if commit.ParentCount() == 0 { cmd.AddArguments("show").AddDynamicArguments(endCommit).AddDashesAndList(files...) } else { - c, err := commit.Parent(0) + c, err := commit.Parent(repo, 0) if err != nil { return nil, err } @@ -90,7 +90,7 @@ func getRepoRawDiffForFileCmd(_ context.Context, repo *Repository, startCommit, } else if commit.ParentCount() == 0 { cmd.AddArguments("format-patch", "--no-signature", "--stdout", "--root").AddDynamicArguments(endCommit).AddDashesAndList(files...) } else { - c, err := commit.Parent(0) + c, err := commit.Parent(repo, 0) if err != nil { return nil, err } diff --git a/modules/git/languagestats/language_stats_gogit.go b/modules/git/languagestats/language_stats_gogit.go index 090ac532745..d8668a43a85 100644 --- a/modules/git/languagestats/language_stats_gogit.go +++ b/modules/git/languagestats/language_stats_gogit.go @@ -7,6 +7,7 @@ package languagestats import ( "bytes" + "context" "io" "gitea.dev/modules/analyze" @@ -21,7 +22,7 @@ import ( ) // GetLanguageStats calculates language stats for git repository at specified commit -func GetLanguageStats(repo *git_module.Repository, commitID string) (map[string]int64, error) { +func GetLanguageStats(_ context.Context, repo *git_module.Repository, commitID string) (map[string]int64, error) { r, err := git.PlainOpen(repo.Path) if err != nil { return nil, err diff --git a/modules/git/languagestats/language_stats_nogogit.go b/modules/git/languagestats/language_stats_nogogit.go index de431ee33af..1467ee9b9ec 100644 --- a/modules/git/languagestats/language_stats_nogogit.go +++ b/modules/git/languagestats/language_stats_nogogit.go @@ -7,6 +7,7 @@ package languagestats import ( "bytes" + "context" "io" "gitea.dev/modules/analyze" @@ -19,10 +20,10 @@ import ( ) // GetLanguageStats calculates language stats for git repository at specified commit -func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, error) { +func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string) (map[string]int64, error) { // We will feed the commit IDs in order into cat-file --batch, followed by blobs as necessary. // so let's create a batch stdin and stdout - batch, cancel, err := repo.CatFileBatch(repo.Ctx) + batch, cancel, err := repo.CatFileBatch(ctx) if err != nil { return nil, err } @@ -43,7 +44,7 @@ func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, return nil, git.ErrNotExist{ID: commitID} } - commit, err := git.CommitFromReader(repo, sha, io.LimitReader(batchReader, commitInfo.Size)) + commit, err := git.CommitFromReader(sha, io.LimitReader(batchReader, commitInfo.Size)) if err != nil { log.Debug("Unable to get commit for: %s. Err: %v", commitID, err) return nil, err @@ -52,9 +53,7 @@ func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, return nil, err } - tree := commit.Tree - - entries, err := tree.ListEntriesRecursiveWithSize() + entries, err := commit.Tree().ListEntriesRecursiveWithSize(ctx, repo) if err != nil { return nil, err } @@ -81,13 +80,15 @@ func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, select { case <-repo.Ctx.Done(): return sizes, repo.Ctx.Err() + case <-ctx.Done(): + return sizes, ctx.Err() default: } contentBuf.Reset() content = contentBuf.Bytes() - if f.Size() == 0 { + if f.GetSize(ctx, repo) == 0 { continue } @@ -124,7 +125,7 @@ func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, } // this language will always be added to the size - sizes[language] += f.Size() + sizes[language] += f.GetSize(ctx, repo) continue } } @@ -138,7 +139,7 @@ func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, // If content can not be read or file is too big just do detection by filename - if f.Size() <= bigFileSize { + if f.GetSize(ctx, repo) <= bigFileSize { info, _, err := batch.QueryContent(f.ID.String()) if err != nil { return nil, err @@ -192,10 +193,10 @@ func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, includedLanguage[language] = included } if included || isDetectable.ValueOrDefault(false) { - sizes[language] += f.Size() + sizes[language] += f.GetSize(ctx, repo) } else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) { firstExcludedLanguage = language - firstExcludedLanguageSize += f.Size() + firstExcludedLanguageSize += f.GetSize(ctx, repo) } } diff --git a/modules/git/languagestats/language_stats_test.go b/modules/git/languagestats/language_stats_test.go index 1953559f914..9776cef500f 100644 --- a/modules/git/languagestats/language_stats_test.go +++ b/modules/git/languagestats/language_stats_test.go @@ -22,7 +22,7 @@ func TestRepository_GetLanguageStats(t *testing.T) { require.NoError(t, err) defer gitRepo.Close() - stats, err := GetLanguageStats(gitRepo, "8fee858da5796dfb37704761701bb8e800ad9ef3") + stats, err := GetLanguageStats(t.Context(), gitRepo, "8fee858da5796dfb37704761701bb8e800ad9ef3") require.NoError(t, err) assert.Equal(t, map[string]int64{ diff --git a/modules/git/last_commit_cache_gogit.go b/modules/git/last_commit_cache_gogit.go index 3afc2130942..b4b2368d2d7 100644 --- a/modules/git/last_commit_cache_gogit.go +++ b/modules/git/last_commit_cache_gogit.go @@ -13,26 +13,26 @@ import ( ) // CacheCommit will cache the commit from the gitRepository -func (c *Commit) CacheCommit(ctx context.Context) error { - if c.repo.LastCommitCache == nil { +func (c *Commit) CacheCommit(ctx context.Context, gitRepo *Repository) error { + if gitRepo.LastCommitCache == nil { return nil } - commitNodeIndex, _ := c.repo.CommitNodeIndex() + commitNodeIndex, _ := gitRepo.CommitNodeIndex() index, err := commitNodeIndex.Get(plumbing.Hash(c.ID.RawValue())) if err != nil { return err } - return c.recursiveCache(ctx, index, &c.Tree, "", 1) + return c.recursiveCache(ctx, gitRepo, index, c.Tree(), "", 1) } -func (c *Commit) recursiveCache(ctx context.Context, index cgobject.CommitNode, tree *Tree, treePath string, level int) error { +func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, index cgobject.CommitNode, tree *Tree, treePath string, level int) error { if level == 0 { return nil } - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(ctx, gitRepo) if err != nil { return err } @@ -44,18 +44,18 @@ func (c *Commit) recursiveCache(ctx context.Context, index cgobject.CommitNode, entryMap[entry.Name()] = entry } - commits, err := GetLastCommitForPaths(ctx, c.repo.LastCommitCache, index, treePath, entryPaths) + commits, err := getLastCommitForPathsByCommitNode(ctx, gitRepo, index, treePath, entryPaths) if err != nil { return err } for entry := range commits { if entryMap[entry].IsDir() { - subTree, err := tree.SubTree(entry) + subTree, err := tree.SubTree(ctx, gitRepo, entry) if err != nil { return err } - if err := c.recursiveCache(ctx, index, subTree, entry, level-1); err != nil { + if err := c.recursiveCache(ctx, gitRepo, index, subTree, entry, level-1); err != nil { return err } } diff --git a/modules/git/last_commit_cache_nogogit.go b/modules/git/last_commit_cache_nogogit.go index e034eaa1680..4956cc698e4 100644 --- a/modules/git/last_commit_cache_nogogit.go +++ b/modules/git/last_commit_cache_nogogit.go @@ -10,19 +10,18 @@ import ( ) // CacheCommit will cache the commit from the gitRepository -func (c *Commit) CacheCommit(ctx context.Context) error { - if c.repo.LastCommitCache == nil { +func (c *Commit) CacheCommit(ctx context.Context, gitRepo *Repository) error { + if gitRepo.LastCommitCache == nil { return nil } - return c.recursiveCache(ctx, &c.Tree, "", 1) + return c.recursiveCache(ctx, gitRepo, c.Tree(), "", 1) } -func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string, level int) error { +func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, tree *Tree, treePath string, level int) error { if level == 0 { return nil } - - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(ctx, gitRepo) if err != nil { return err } @@ -32,7 +31,7 @@ func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string entryPaths[i] = entry.Name() } - _, err = walkGitLog(ctx, c.repo, c, treePath, entryPaths...) + _, err = walkGitLog(ctx, gitRepo, c, treePath, entryPaths...) if err != nil { return err } @@ -40,11 +39,11 @@ func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string for _, treeEntry := range entries { // entryMap won't contain "" therefore skip this. if treeEntry.IsDir() { - subTree, err := tree.SubTree(treeEntry.Name()) + subTree, err := tree.SubTree(ctx, gitRepo, treeEntry.Name()) if err != nil { return err } - if err := c.recursiveCache(ctx, subTree, treeEntry.Name(), level-1); err != nil { + if err := c.recursiveCache(ctx, gitRepo, subTree, treeEntry.Name(), level-1); err != nil { return err } } diff --git a/modules/git/log_name_status_nogogit.go b/modules/git/log_name_status_nogogit.go index b11645833d8..05924fca11b 100644 --- a/modules/git/log_name_status_nogogit.go +++ b/modules/git/log_name_status_nogogit.go @@ -263,13 +263,12 @@ var walkGitLogDebugBeforeNext func() // is used to simulate various edge git pro // walkGitLog walks the git log --name-status for the head commit in the provided treepath and files func walkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath string, paths ...string) (map[string]string, error) { headRef := head.ID.String() - - tree, err := head.SubTree(treepath) + tree, err := head.SubTree(ctx, repo, treepath) if err != nil { return nil, err } - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(ctx, repo) if err != nil { return nil, err } diff --git a/modules/git/notes.go b/modules/git/notes.go index 63539cb3a23..3b7fadccd48 100644 --- a/modules/git/notes.go +++ b/modules/git/notes.go @@ -3,6 +3,14 @@ package git +import ( + "context" + "io" + "strings" + + "gitea.dev/modules/log" +) + // 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" @@ -12,3 +20,80 @@ type Note struct { Message []byte Commit *Commit } + +// GetNote retrieves the git-notes data for a given commit. +// FIXME: Add LastCommitCache support +func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note) error { + log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path) + notes, err := repo.GetCommit(NotesRef) + if err != nil { + if IsErrNotExist(err) { + return err + } + log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err) + return err + } + + path := "" + + tree := notes.Tree() + log.Trace("Found tree with ID %q while searching for git note corresponding to the commit %q", tree.ID, commitID) + + var entry *TreeEntry + originalCommitID := commitID + for len(commitID) > 2 { + entry, err = tree.GetTreeEntryByPath(ctx, repo, commitID) + if err == nil { + path += commitID + break + } + if IsErrNotExist(err) { + tree, err = tree.SubTree(ctx, repo, commitID[0:2]) + path += commitID[0:2] + "/" + commitID = commitID[2:] + } + if err != nil { + // Err may have been updated by the SubTree we need to recheck if it's again an ErrNotExist + if !IsErrNotExist(err) { + log.Error("Unable to find git note corresponding to the commit %q. Error: %v", originalCommitID, err) + } + return err + } + } + + blob := entry.Blob(repo) + dataRc, err := blob.DataAsync() + if err != nil { + log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err) + return err + } + closed := false + defer func() { + if !closed { + _ = dataRc.Close() + } + }() + d, err := io.ReadAll(dataRc) + if err != nil { + log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err) + return err + } + _ = dataRc.Close() + closed = true + note.Message = d + + treePath := "" + if idx := strings.LastIndex(path, "/"); idx > -1 { + treePath = path[:idx] + path = path[idx+1:] + } + + lastCommits, err := GetLastCommitForPaths(ctx, repo, notes, treePath, []string{path}) + if err != nil { + log.Error("Unable to get the commit for the path %q. Error: %v", treePath, err) + return err + } + note.Commit = lastCommits[path] + + return nil +} diff --git a/modules/git/notes_gogit.go b/modules/git/notes_gogit.go deleted file mode 100644 index a4cf575ad41..00000000000 --- a/modules/git/notes_gogit.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2019 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build gogit - -package git - -import ( - "context" - "fmt" - "io" - "strings" - - "gitea.dev/modules/log" - - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/object" -) - -// GetNote retrieves the git-notes data for a given commit. -// FIXME: Add LastCommitCache support -func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note) error { - log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path) - notes, err := repo.GetCommit(NotesRef) - if err != nil { - if IsErrNotExist(err) { - return err - } - log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err) - return err - } - - remainingCommitID := commitID - var path strings.Builder - currentTree, err := notes.Tree.gogitTreeObject() - if err != nil { - return fmt.Errorf("unable to get tree object for notes commit %q: %w", notes.ID.String(), err) - } - - log.Trace("Found tree with ID %q while searching for git note corresponding to the commit %q", currentTree.Entries[0].Name, commitID) - var file *object.File - for len(remainingCommitID) > 2 { - file, err = currentTree.File(remainingCommitID) - if err == nil { - path.WriteString(remainingCommitID) - break - } - if err == object.ErrFileNotFound { - currentTree, err = currentTree.Tree(remainingCommitID[0:2]) - path.WriteString(remainingCommitID[0:2] + "/") - remainingCommitID = remainingCommitID[2:] - } - if err != nil { - if err == object.ErrDirectoryNotFound { - return ErrNotExist{ID: remainingCommitID, RelPath: path.String()} - } - log.Error("Unable to find git note corresponding to the commit %q. Error: %v", commitID, err) - return err - } - } - - blob := file.Blob - dataRc, err := blob.Reader() - if err != nil { - log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err) - return err - } - - defer dataRc.Close() - d, err := io.ReadAll(dataRc) - if err != nil { - log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err) - return err - } - note.Message = d - - commitNodeIndex, commitGraphFile := repo.CommitNodeIndex() - if commitGraphFile != nil { - defer commitGraphFile.Close() - } - - commitNode, err := commitNodeIndex.Get(plumbing.Hash(notes.ID.RawValue())) - if err != nil { - return err - } - - lastCommits, err := GetLastCommitForPaths(ctx, nil, commitNode, "", []string{path.String()}) - if err != nil { - log.Error("Unable to get the commit for the path %q. Error: %v", path.String(), err) - return err - } - note.Commit = lastCommits[path.String()] - - return nil -} diff --git a/modules/git/notes_nogogit.go b/modules/git/notes_nogogit.go deleted file mode 100644 index 09ee53f6931..00000000000 --- a/modules/git/notes_nogogit.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2019 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build !gogit - -package git - -import ( - "context" - "io" - "strings" - - "gitea.dev/modules/log" -) - -// GetNote retrieves the git-notes data for a given commit. -// FIXME: Add LastCommitCache support -func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note) error { - log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path) - notes, err := repo.GetCommit(NotesRef) - if err != nil { - if IsErrNotExist(err) { - return err - } - log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err) - return err - } - - path := "" - - tree := ¬es.Tree - log.Trace("Found tree with ID %q while searching for git note corresponding to the commit %q", tree.ID, commitID) - - var entry *TreeEntry - originalCommitID := commitID - for len(commitID) > 2 { - entry, err = tree.GetTreeEntryByPath(commitID) - if err == nil { - path += commitID - break - } - if IsErrNotExist(err) { - tree, err = tree.SubTree(commitID[0:2]) - path += commitID[0:2] + "/" - commitID = commitID[2:] - } - if err != nil { - // Err may have been updated by the SubTree we need to recheck if it's again an ErrNotExist - if !IsErrNotExist(err) { - log.Error("Unable to find git note corresponding to the commit %q. Error: %v", originalCommitID, err) - } - return err - } - } - - blob := entry.Blob() - dataRc, err := blob.DataAsync() - if err != nil { - log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err) - return err - } - closed := false - defer func() { - if !closed { - _ = dataRc.Close() - } - }() - d, err := io.ReadAll(dataRc) - if err != nil { - log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err) - return err - } - _ = dataRc.Close() - closed = true - note.Message = d - - treePath := "" - if idx := strings.LastIndex(path, "/"); idx > -1 { - treePath = path[:idx] - path = path[idx+1:] - } - - lastCommits, err := GetLastCommitForPaths(ctx, notes, treePath, []string{path}) - if err != nil { - log.Error("Unable to get the commit for the path %q. Error: %v", treePath, err) - return err - } - note.Commit = lastCommits[path] - - return nil -} diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go index 8b596e9b056..d4862f070d2 100644 --- a/modules/git/pipeline/lfs_nogogit.go +++ b/modules/git/pipeline/lfs_nogogit.go @@ -72,7 +72,7 @@ func findLFSFileFunc(repo *git.Repository, objectID git.ObjectID, revListReader continue case "commit": // Read in the commit to get its tree and in case this is one of the last used commits - curCommit, err = git.CommitFromReader(repo, git.MustIDFromString(commitID), io.LimitReader(batchReader, info.Size)) + curCommit, err = git.CommitFromReader(git.MustIDFromString(commitID), io.LimitReader(batchReader, info.Size)) if err != nil { return nil, err } @@ -80,7 +80,7 @@ func findLFSFileFunc(repo *git.Repository, objectID git.ObjectID, revListReader return nil, err } - if info, _, err = batch.QueryContent(curCommit.Tree.ID.String()); err != nil { + if info, _, err = batch.QueryContent(curCommit.TreeID.String()); err != nil { return nil, err } curPath = "" diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go index a7e9731b155..b1f0a20d5ad 100644 --- a/modules/git/repo_commit_gogit.go +++ b/modules/git/repo_commit_gogit.go @@ -92,15 +92,14 @@ func (repo *Repository) getCommit(id ObjectID) (*Commit, error) { } commit := convertCommit(gogitCommit) - commit.repo = repo tree, err := gogitCommit.Tree() if err != nil { return nil, err } - commit.Tree.ID = ParseGogitHash(tree.Hash) - commit.Tree.resolvedGogitTreeObject = tree + commit.TreeID = ParseGogitHash(tree.Hash) + commit.Tree().resolvedGogitTreeObject = tree return commit, nil } diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index d8b842beeed..425def5234c 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -88,7 +88,7 @@ func (repo *Repository) getCommitWithBatch(batch CatFileBatch, id ObjectID) (*Co } return repo.getCommitWithBatch(batch, tag.Object) case "commit": - commit, err := CommitFromReader(repo, id, io.LimitReader(rd, info.Size)) + commit, err := CommitFromReader(id, io.LimitReader(rd, info.Size)) if err != nil { return nil, err } diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go index 957bb6ee328..96958e384e4 100644 --- a/modules/git/repo_index.go +++ b/modules/git/repo_index.go @@ -149,5 +149,5 @@ func (repo *Repository) WriteTree() (*Tree, error) { if err != nil { return nil, err } - return NewTree(repo, id), nil + return newTree(id), nil } diff --git a/modules/git/repo_tree_gogit.go b/modules/git/repo_tree_gogit.go index 622052d64d6..4f9a07d32f8 100644 --- a/modules/git/repo_tree_gogit.go +++ b/modules/git/repo_tree_gogit.go @@ -25,7 +25,7 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) { return nil, err } - tree := NewTree(repo, id) + tree := newTree(id) tree.resolvedGogitTreeObject = gogitTree return tree, nil } @@ -53,7 +53,6 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) { if err != nil { return nil, err } - resolvedID := id commitObject, err := repo.gogitRepo.CommitObject(plumbing.Hash(id.RawValue())) if err == nil { id = ParseGogitHash(commitObject.TreeHash) @@ -62,6 +61,5 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) { if err != nil { return nil, err } - treeObject.ResolvedID = resolvedID return treeObject, nil } diff --git a/modules/git/repo_tree_nogogit.go b/modules/git/repo_tree_nogogit.go index 82a61072c9d..2527897bd34 100644 --- a/modules/git/repo_tree_nogogit.go +++ b/modules/git/repo_tree_nogogit.go @@ -23,7 +23,6 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) { switch info.Type { case "tag": - resolvedID := id data, err := io.ReadAll(io.LimitReader(rd, info.Size)) if err != nil { return nil, err @@ -37,21 +36,20 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) { if err != nil { return nil, err } - commit.Tree.ResolvedID = resolvedID - return &commit.Tree, nil + tree := commit.Tree() + return tree, nil case "commit": - commit, err := CommitFromReader(repo, id, io.LimitReader(rd, info.Size)) + commit, err := CommitFromReader(id, io.LimitReader(rd, info.Size)) if err != nil { return nil, err } if _, err := rd.Discard(1); err != nil { return nil, err } - commit.Tree.ResolvedID = commit.ID - return &commit.Tree, nil + tree := commit.Tree() + return tree, nil case "tree": - tree := NewTree(repo, id) - tree.ResolvedID = id + tree := newTree(id) objectFormat, err := repo.GetObjectFormat() if err != nil { return nil, err diff --git a/modules/git/tree.go b/modules/git/tree.go index 854f45c56f4..f19c6dbc023 100644 --- a/modules/git/tree.go +++ b/modules/git/tree.go @@ -6,31 +6,22 @@ package git import ( "bytes" + "context" "strings" "gitea.dev/modules/git/gitcmd" ) type TreeCommon struct { - ID ObjectID - ResolvedID ObjectID - - repo *Repository - ptree *Tree // parent tree + ID ObjectID } -// NewTree create a new tree according the repository and tree id -func NewTree(repo *Repository, id ObjectID) *Tree { - return &Tree{ - TreeCommon: TreeCommon{ - ID: id, - repo: repo, - }, - } +func newTree(id ObjectID) *Tree { + return &Tree{TreeCommon: TreeCommon{ID: id}} } // SubTree get a subtree by the sub dir path -func (t *Tree) SubTree(rpath string) (*Tree, error) { +func (t *Tree) SubTree(ctx context.Context, gitRepo *Repository, rpath string) (*Tree, error) { if len(rpath) == 0 { return t, nil } @@ -43,16 +34,15 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) { te *TreeEntry ) for _, name := range paths { - te, err = p.GetTreeEntryByPath(name) + te, err = p.GetTreeEntryByPath(ctx, gitRepo, name) if err != nil { return nil, err } - g, err = t.repo.getTree(te.ID) + g, err = gitRepo.getTree(te.ID) if err != nil { return nil, err } - g.ptree = p p = g } return g, nil diff --git a/modules/git/tree_blob.go b/modules/git/tree_blob.go index 31d9f3d73b2..8f36bce35b0 100644 --- a/modules/git/tree_blob.go +++ b/modules/git/tree_blob.go @@ -4,15 +4,17 @@ package git +import "context" + // GetBlobByPath get the blob object according the path -func (t *Tree) GetBlobByPath(relpath string) (*Blob, error) { - entry, err := t.GetTreeEntryByPath(relpath) +func (t *Tree) GetBlobByPath(ctx context.Context, gitRepo *Repository, relpath string) (*Blob, error) { + entry, err := t.GetTreeEntryByPath(ctx, gitRepo, relpath) if err != nil { return nil, err } if !entry.IsDir() && !entry.IsSubModule() { - return entry.Blob(), nil + return entry.Blob(gitRepo), nil } return nil, ErrNotExist{"", relpath} diff --git a/modules/git/tree_blob_gogit.go b/modules/git/tree_blob_gogit.go index 2c0ff0e1b0d..84f08c2e662 100644 --- a/modules/git/tree_blob_gogit.go +++ b/modules/git/tree_blob_gogit.go @@ -7,6 +7,7 @@ package git import ( + "context" "path" "strings" @@ -14,7 +15,7 @@ import ( ) // GetTreeEntryByPath get the tree entries according the sub dir -func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) { +func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relpath string) (*TreeEntry, error) { if len(relpath) == 0 { return &TreeEntry{ ID: t.ID, @@ -30,7 +31,7 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) { tree := t for i, name := range parts { if i == len(parts)-1 { - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(ctx, gitRepo) if err != nil { if err == plumbing.ErrObjectNotFound { return nil, ErrNotExist{ @@ -45,7 +46,7 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) { } } } else { - tree, err = tree.SubTree(name) + tree, err = tree.SubTree(ctx, gitRepo, name) if err != nil { if err == plumbing.ErrObjectNotFound { return nil, ErrNotExist{ diff --git a/modules/git/tree_blob_nogogit.go b/modules/git/tree_blob_nogogit.go index b18d0fa05e6..26830728181 100644 --- a/modules/git/tree_blob_nogogit.go +++ b/modules/git/tree_blob_nogogit.go @@ -6,12 +6,13 @@ package git import ( + "context" "path" "strings" ) // GetTreeEntryByPath get the tree entries according the sub dir -func (t *Tree) GetTreeEntryByPath(relpath string) (_ *TreeEntry, err error) { +func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relpath string) (_ *TreeEntry, err error) { if len(relpath) == 0 { return &TreeEntry{ ptree: t, @@ -26,14 +27,14 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (_ *TreeEntry, err error) { tree := t for _, name := range parts[:len(parts)-1] { - tree, err = tree.SubTree(name) + tree, err = tree.SubTree(ctx, gitRepo, name) if err != nil { return nil, err } } name := parts[len(parts)-1] - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(ctx, gitRepo) if err != nil { return nil, err } diff --git a/modules/git/tree_entry.go b/modules/git/tree_entry.go index bd7e5131b53..690e1965660 100644 --- a/modules/git/tree_entry.go +++ b/modules/git/tree_entry.go @@ -5,6 +5,7 @@ package git import ( + "context" "path" "slices" "strings" @@ -78,18 +79,18 @@ type EntryFollowResult struct { TargetEntry *TreeEntry } -func EntryFollowLink(commit *Commit, fullPath string, te *TreeEntry) (*EntryFollowResult, error) { +func EntryFollowLink(ctx context.Context, gitRepo *Repository, commit *Commit, fullPath string, te *TreeEntry) (*EntryFollowResult, error) { if !te.IsLink() { return nil, util.ErrorWrap(util.ErrUnprocessableContent, "%q is not a symlink", fullPath) } // git's filename max length is 4096, hopefully a link won't be longer than multiple of that const maxSymlinkSize = 20 * 4096 - if te.Blob().Size() > maxSymlinkSize { + if te.Blob(gitRepo).Size() > maxSymlinkSize { return nil, util.ErrorWrap(util.ErrUnprocessableContent, "%q content exceeds symlink limit", fullPath) } - link, err := te.Blob().GetBlobContent(maxSymlinkSize) + link, err := te.Blob(gitRepo).GetBlobContent(maxSymlinkSize) if err != nil { return nil, err } @@ -99,18 +100,18 @@ func EntryFollowLink(commit *Commit, fullPath string, te *TreeEntry) (*EntryFoll } targetFullPath := path.Join(path.Dir(fullPath), link) - targetEntry, err := commit.GetTreeEntryByPath(targetFullPath) + targetEntry, err := commit.GetTreeEntryByPath(ctx, gitRepo, targetFullPath) if err != nil { return &EntryFollowResult{SymlinkContent: link}, err } return &EntryFollowResult{SymlinkContent: link, TargetFullPath: targetFullPath, TargetEntry: targetEntry}, nil } -func EntryFollowLinks(commit *Commit, firstFullPath string, firstTreeEntry *TreeEntry, optLimit ...int) (res *EntryFollowResult, err error) { +func EntryFollowLinks(ctx context.Context, gitRepo *Repository, commit *Commit, firstFullPath string, firstTreeEntry *TreeEntry, optLimit ...int) (res *EntryFollowResult, err error) { limit := util.OptionalArg(optLimit, 10) treeEntry, fullPath := firstTreeEntry, firstFullPath for range limit { - res, err = EntryFollowLink(commit, fullPath, treeEntry) + res, err = EntryFollowLink(ctx, gitRepo, commit, fullPath, treeEntry) if err != nil { return res, err } @@ -125,28 +126,26 @@ func EntryFollowLinks(commit *Commit, firstFullPath string, firstTreeEntry *Tree return res, nil } -// returns the Tree pointed to by this TreeEntry, or nil if this is not a tree -func (te *TreeEntry) Tree() *Tree { - t, err := te.ptree.repo.getTree(te.ID) +func (te *TreeEntry) Tree(gitRepo *Repository) *Tree { + t, err := gitRepo.getTree(te.ID) if err != nil { return nil } - t.ptree = te.ptree return t } // GetSubJumpablePathName return the full path of subdirectory jumpable ( contains only one directory ) -func (te *TreeEntry) GetSubJumpablePathName() string { +func (te *TreeEntry) GetSubJumpablePathName(ctx context.Context, gitRepo *Repository) string { if te.IsSubModule() || !te.IsDir() { return "" } - tree, err := te.ptree.SubTree(te.Name()) + tree, err := te.ptree.SubTree(ctx, gitRepo, te.Name()) if err != nil { return te.Name() } - entries, _ := tree.ListEntries() + entries, _ := tree.ListEntries(ctx, gitRepo) if len(entries) == 1 && entries[0].IsDir() { - name := entries[0].GetSubJumpablePathName() + name := entries[0].GetSubJumpablePathName(ctx, gitRepo) if name != "" { return te.Name() + "/" + name } diff --git a/modules/git/tree_entry_common_test.go b/modules/git/tree_entry_common_test.go index 2907077693f..95722dc4488 100644 --- a/modules/git/tree_entry_common_test.go +++ b/modules/git/tree_entry_common_test.go @@ -23,12 +23,12 @@ func TestFollowLink(t *testing.T) { // get the symlink { lnkFullPath := "foo/bar/link_to_hello" - lnk, err := commit.Tree.GetTreeEntryByPath("foo/bar/link_to_hello") + lnk, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/bar/link_to_hello") require.NoError(t, err) assert.True(t, lnk.IsLink()) // should be able to dereference to target - res, err := EntryFollowLink(commit, lnkFullPath, lnk) + res, err := EntryFollowLink(t.Context(), r, commit, lnkFullPath, lnk) require.NoError(t, err) assert.Equal(t, "hello", res.TargetEntry.Name()) assert.Equal(t, "foo/nar/hello", res.TargetFullPath) @@ -38,38 +38,38 @@ func TestFollowLink(t *testing.T) { { // should error when called on a normal file - entry, err := commit.Tree.GetTreeEntryByPath("file1.txt") + entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "file1.txt") require.NoError(t, err) - res, err := EntryFollowLink(commit, "file1.txt", entry) + res, err := EntryFollowLink(t.Context(), r, commit, "file1.txt", entry) assert.ErrorIs(t, err, util.ErrUnprocessableContent) assert.Nil(t, res) } { // should error for broken links - entry, err := commit.Tree.GetTreeEntryByPath("foo/broken_link") + entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/broken_link") require.NoError(t, err) assert.True(t, entry.IsLink()) - res, err := EntryFollowLink(commit, "foo/broken_link", entry) + res, err := EntryFollowLink(t.Context(), r, commit, "foo/broken_link", entry) assert.ErrorIs(t, err, util.ErrNotExist) assert.Equal(t, "nar/broken_link", res.SymlinkContent) } { // should error for external links - entry, err := commit.Tree.GetTreeEntryByPath("foo/outside_repo") + entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/outside_repo") require.NoError(t, err) assert.True(t, entry.IsLink()) - res, err := EntryFollowLink(commit, "foo/outside_repo", entry) + res, err := EntryFollowLink(t.Context(), r, commit, "foo/outside_repo", entry) assert.ErrorIs(t, err, util.ErrNotExist) assert.Equal(t, "../../outside_repo", res.SymlinkContent) } { // testing fix for short link bug - entry, err := commit.Tree.GetTreeEntryByPath("foo/link_short") + entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/link_short") require.NoError(t, err) - res, err := EntryFollowLink(commit, "foo/link_short", entry) + res, err := EntryFollowLink(t.Context(), r, commit, "foo/link_short", entry) assert.ErrorIs(t, err, util.ErrNotExist) assert.Equal(t, "a", res.SymlinkContent) } diff --git a/modules/git/tree_entry_gogit.go b/modules/git/tree_entry_gogit.go index f092e70636b..f19d2dc1645 100644 --- a/modules/git/tree_entry_gogit.go +++ b/modules/git/tree_entry_gogit.go @@ -7,6 +7,8 @@ package git import ( + "context" + "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/object" @@ -29,15 +31,15 @@ func (te *TreeEntry) toGogitTreeEntry() *object.TreeEntry { } } -// Size returns the size of the entry -func (te *TreeEntry) Size() int64 { +// GetSize returns the size of the entry +func (te *TreeEntry) GetSize(ctx context.Context, gitRepo *Repository) int64 { if te.IsDir() { return 0 } else if te.sized { return te.size } - ptreeGogitTree, err := te.ptree.gogitTreeObject() + ptreeGogitTree, err := te.ptree.gogitTreeObject(gitRepo) if err != nil { return 0 } @@ -52,10 +54,10 @@ func (te *TreeEntry) Size() int64 { } // Blob returns the blob object the entry -func (te *TreeEntry) Blob() *Blob { +func (te *TreeEntry) Blob(gitRepo *Repository) *Blob { return &Blob{ ID: te.ID, - repo: te.ptree.repo, + repo: gitRepo, name: te.Name(), } } diff --git a/modules/git/tree_entry_nogogit.go b/modules/git/tree_entry_nogogit.go index 467a0d76950..53e1e1aef51 100644 --- a/modules/git/tree_entry_nogogit.go +++ b/modules/git/tree_entry_nogogit.go @@ -5,25 +5,28 @@ package git -import "gitea.dev/modules/log" +import ( + "context" -// Size returns the size of the entry -func (te *TreeEntry) Size() int64 { + "gitea.dev/modules/log" +) + +func (te *TreeEntry) GetSize(ctx context.Context, gitRepo *Repository) int64 { if te.IsDir() { return 0 } else if te.sized { return te.size } - batch, cancel, err := te.ptree.repo.CatFileBatch(te.ptree.repo.Ctx) + batch, cancel, err := gitRepo.CatFileBatch(ctx) if err != nil { - log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err) + log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), gitRepo.Path, err) return 0 } defer cancel() info, err := batch.QueryInfo(te.ID.String()) if err != nil { - log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err) + log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), gitRepo.Path, err) return 0 } @@ -33,12 +36,12 @@ func (te *TreeEntry) Size() int64 { } // Blob returns the blob object the entry -func (te *TreeEntry) Blob() *Blob { +func (te *TreeEntry) Blob(gitRepo *Repository) *Blob { return &Blob{ ID: te.ID, name: te.Name(), size: te.size, gotSize: te.sized, - repo: te.ptree.repo, + repo: gitRepo, } } diff --git a/modules/git/tree_gogit.go b/modules/git/tree_gogit.go index fec6e2704e6..2255b10f593 100644 --- a/modules/git/tree_gogit.go +++ b/modules/git/tree_gogit.go @@ -7,6 +7,7 @@ package git import ( + "context" "io" "github.com/go-git/go-git/v5/plumbing" @@ -20,9 +21,9 @@ type Tree struct { resolvedGogitTreeObject *object.Tree } -func (t *Tree) gogitTreeObject() (_ *object.Tree, err error) { +func (t *Tree) gogitTreeObject(gitRepo *Repository) (_ *object.Tree, err error) { if t.resolvedGogitTreeObject == nil { - t.resolvedGogitTreeObject, err = t.repo.gogitRepo.TreeObject(plumbing.Hash(t.ID.RawValue())) + t.resolvedGogitTreeObject, err = gitRepo.gogitRepo.TreeObject(plumbing.Hash(t.ID.RawValue())) if err != nil { return nil, err } @@ -31,8 +32,8 @@ func (t *Tree) gogitTreeObject() (_ *object.Tree, err error) { } // ListEntries returns all entries of current tree. -func (t *Tree) ListEntries() (Entries, error) { - gogitTree, err := t.gogitTreeObject() +func (t *Tree) ListEntries(_ context.Context, gitRepo *Repository) (Entries, error) { + gogitTree, err := t.gogitTreeObject(gitRepo) if err != nil { return nil, err } @@ -50,8 +51,8 @@ func (t *Tree) ListEntries() (Entries, error) { } // ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees -func (t *Tree) ListEntriesRecursiveWithSize() (entries Entries, _ error) { - gogitTree, err := t.gogitTreeObject() +func (t *Tree) ListEntriesRecursiveWithSize(_ context.Context, gitRepo *Repository) (entries Entries, _ error) { + gogitTree, err := t.gogitTreeObject(gitRepo) if err != nil { return nil, err } @@ -76,6 +77,6 @@ func (t *Tree) ListEntriesRecursiveWithSize() (entries Entries, _ error) { } // ListEntriesRecursiveFast is the alias of ListEntriesRecursiveWithSize for the gogit version -func (t *Tree) ListEntriesRecursiveFast() (Entries, error) { - return t.ListEntriesRecursiveWithSize() +func (t *Tree) ListEntriesRecursiveFast(ctx context.Context, gitRepo *Repository) (Entries, error) { + return t.ListEntriesRecursiveWithSize(ctx, gitRepo) } diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index ebb4c7bb122..502a3c65859 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -6,6 +6,7 @@ package git import ( + "context" "io" "gitea.dev/modules/git/gitcmd" @@ -20,49 +21,47 @@ type Tree struct { } // ListEntries returns all entries of current tree. -func (t *Tree) ListEntries() (Entries, error) { +func (t *Tree) ListEntries(ctx context.Context, gitRepo *Repository) (Entries, error) { if t.entriesParsed { return t.entries, nil } - if t.repo != nil { - batch, cancel, err := t.repo.CatFileBatch(t.repo.Ctx) - if err != nil { + batch, cancel, err := gitRepo.CatFileBatch(ctx) + if err != nil { + return nil, err + } + defer cancel() + + info, rd, err := batch.QueryContent(t.ID.String()) + if err != nil { + return nil, err + } + + if info.Type == "commit" { + treeID, err := ReadTreeID(rd, info.Size) + if err != nil && err != io.EOF { return nil, err } - defer cancel() - - info, rd, err := batch.QueryContent(t.ID.String()) + info, rd, err = batch.QueryContent(treeID) if err != nil { return nil, err } - - if info.Type == "commit" { - treeID, err := ReadTreeID(rd, info.Size) - if err != nil && err != io.EOF { - return nil, err - } - info, rd, err = batch.QueryContent(treeID) - if err != nil { - return nil, err - } - } - if info.Type == "tree" { - t.entries, err = catBatchParseTreeEntries(t.ID.Type(), t, rd, info.Size) - if err != nil { - return nil, err - } - t.entriesParsed = true - return t.entries, nil - } - - // Not a tree just use ls-tree instead - if err := DiscardFull(rd, info.Size+1); err != nil { - return nil, err - } + } + if info.Type == "tree" { + t.entries, err = catBatchParseTreeEntries(t.ID.Type(), t, rd, info.Size) + if err != nil { + return nil, err + } + t.entriesParsed = true + return t.entries, nil } - stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithDir(t.repo.Path).RunStdBytes(t.repo.Ctx) + // Not a tree just use ls-tree instead + if err := DiscardFull(rd, info.Size+1); err != nil { + return nil, err + } + + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithDir(gitRepo.Path).RunStdBytes(ctx) if runErr != nil { if gitcmd.IsStderr(runErr, gitcmd.StderrNotValidObjectName) || gitcmd.IsStderr(runErr, gitcmd.StderrNotTreeObject) { return nil, ErrNotExist{ @@ -72,7 +71,6 @@ func (t *Tree) ListEntries() (Entries, error) { return nil, runErr } - var err error t.entries, err = parseTreeEntries(stdout, t) if err == nil { t.entriesParsed = true @@ -83,12 +81,12 @@ func (t *Tree) ListEntries() (Entries, error) { // listEntriesRecursive returns all entries of current tree recursively including all subtrees // extraArgs could be "-l" to get the size, which is slower -func (t *Tree) listEntriesRecursive(extraArgs gitcmd.TrustedCmdArgs) (Entries, error) { +func (t *Tree) listEntriesRecursive(ctx context.Context, gitRepo *Repository, extraArgs gitcmd.TrustedCmdArgs) (Entries, error) { stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r"). AddArguments(extraArgs...). AddDynamicArguments(t.ID.String()). - WithDir(t.repo.Path). - RunStdBytes(t.repo.Ctx) + WithDir(gitRepo.Path). + RunStdBytes(ctx) if runErr != nil { return nil, runErr } @@ -99,11 +97,11 @@ func (t *Tree) listEntriesRecursive(extraArgs gitcmd.TrustedCmdArgs) (Entries, e } // ListEntriesRecursiveFast returns all entries of current tree recursively including all subtrees, no size -func (t *Tree) ListEntriesRecursiveFast() (Entries, error) { - return t.listEntriesRecursive(nil) +func (t *Tree) ListEntriesRecursiveFast(ctx context.Context, gitRepo *Repository) (Entries, error) { + return t.listEntriesRecursive(ctx, gitRepo, nil) } // ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size -func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) { - return t.listEntriesRecursive(gitcmd.TrustedCmdArgs{"--long"}) +func (t *Tree) ListEntriesRecursiveWithSize(ctx context.Context, gitRepo *Repository) (Entries, error) { + return t.listEntriesRecursive(ctx, gitRepo, gitcmd.TrustedCmdArgs{"--long"}) } diff --git a/modules/git/tree_test.go b/modules/git/tree_test.go index 67f95fe7489..8b593fe35af 100644 --- a/modules/git/tree_test.go +++ b/modules/git/tree_test.go @@ -20,7 +20,7 @@ func TestSubTree_Issue29101(t *testing.T) { // old code could produce a different error if called multiple times for range 10 { - _, err = commit.SubTree("file1.txt") + _, err = commit.SubTree(t.Context(), repo, "file1.txt") assert.Error(t, err) assert.True(t, IsErrNotExist(err)) } diff --git a/modules/gitrepo/blame.go b/modules/gitrepo/blame.go index e2a5eefa5f4..e98a5ac13f2 100644 --- a/modules/gitrepo/blame.go +++ b/modules/gitrepo/blame.go @@ -139,7 +139,7 @@ func (r *BlameReader) cleanup() { } // CreateBlameReader creates reader for given repository, commit and file -func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, retErr error) { +func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo Repository, gitRepo *git.Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, retErr error) { defer func() { if retErr != nil { rd.cleanup() @@ -158,7 +158,7 @@ func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo rd.cleanupFuncs = append(rd.cleanupFuncs, stdoutReaderClose) if git.DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore { - ignoreRevsFileName, ignoreRevsFileCleanup, err := tryCreateBlameIgnoreRevsFile(commit) + ignoreRevsFileName, ignoreRevsFileCleanup, err := tryCreateBlameIgnoreRevsFile(ctx, gitRepo, commit) if err != nil && !git.IsErrNotExist(err) { return nil, err } else if err == nil { @@ -180,13 +180,13 @@ func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo return rd, nil } -func tryCreateBlameIgnoreRevsFile(commit *git.Commit) (string, func(), error) { - entry, err := commit.GetTreeEntryByPath(".git-blame-ignore-revs") +func tryCreateBlameIgnoreRevsFile(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, func(), error) { + entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, ".git-blame-ignore-revs") if err != nil { return "", nil, err } - r, err := entry.Blob().DataAsync() + r, err := entry.Blob(gitRepo).DataAsync() if err != nil { return "", nil, err } diff --git a/modules/gitrepo/blame_sha256_test.go b/modules/gitrepo/blame_sha256_test.go index 5577432cafd..145210cd6fc 100644 --- a/modules/gitrepo/blame_sha256_test.go +++ b/modules/gitrepo/blame_sha256_test.go @@ -49,7 +49,7 @@ func TestReadingBlameOutputSha256(t *testing.T) { } for _, bypass := range []bool{false, true} { - blameReader, err := CreateBlameReader(ctx, git.Sha256ObjectFormat, storage, commit, "README.md", bypass) + blameReader, err := CreateBlameReader(ctx, git.Sha256ObjectFormat, storage, repo, commit, "README.md", bypass) assert.NoError(t, err) assert.NotNil(t, blameReader) defer blameReader.Close() @@ -134,7 +134,7 @@ func TestReadingBlameOutputSha256(t *testing.T) { for _, c := range cases { commit, err := repo.GetCommit(c.CommitID) assert.NoError(t, err) - blameReader, err := CreateBlameReader(ctx, objectFormat, storage, commit, "blame.txt", c.Bypass) + blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass) assert.NoError(t, err) assert.NotNil(t, blameReader) defer blameReader.Close() diff --git a/modules/gitrepo/blame_test.go b/modules/gitrepo/blame_test.go index 54be64f996b..d760bed69bf 100644 --- a/modules/gitrepo/blame_test.go +++ b/modules/gitrepo/blame_test.go @@ -43,7 +43,7 @@ func TestReadingBlameOutput(t *testing.T) { } for _, bypass := range []bool{false, true} { - blameReader, err := CreateBlameReader(ctx, git.Sha1ObjectFormat, storage, commit, "README.md", bypass) + blameReader, err := CreateBlameReader(ctx, git.Sha1ObjectFormat, storage, repo, commit, "README.md", bypass) assert.NoError(t, err) assert.NotNil(t, blameReader) defer blameReader.Close() @@ -129,7 +129,7 @@ func TestReadingBlameOutput(t *testing.T) { commit, err := repo.GetCommit(c.CommitID) assert.NoError(t, err) - blameReader, err := CreateBlameReader(ctx, objectFormat, storage, commit, "blame.txt", c.Bypass) + blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass) assert.NoError(t, err) assert.NotNil(t, blameReader) defer blameReader.Close() diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go index 88a313c33ed..e1ca1ff4b9a 100644 --- a/modules/indexer/code/git.go +++ b/modules/indexer/code/git.go @@ -26,7 +26,7 @@ func getDefaultBranchSha(ctx context.Context, repo *repo_model.Repository) (stri } // getRepoChanges returns changes to repo since last indexer update -func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { +func getRepoChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, revision string) (*internal.RepoChanges, error) { status, err := repo_model.GetIndexerStatus(ctx, repo, repo_model.RepoIndexerTypeCode) if err != nil { return nil, err @@ -40,9 +40,9 @@ func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision s } if needGenesis { - return genesisChanges(ctx, repo, revision) + return genesisChanges(ctx, repo, gitRepo, revision) } - return nonGenesisChanges(ctx, repo, revision) + return nonGenesisChanges(ctx, repo, gitRepo, revision) } func isIndexable(entry *git.TreeEntry) bool { @@ -64,7 +64,7 @@ func isIndexable(entry *git.TreeEntry) bool { } // parseGitLsTreeOutput parses the output of a `git ls-tree -r --full-name` command -func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) { +func parseGitLsTreeOutput(ctx context.Context, gitRepo *git.Repository, stdout []byte) ([]internal.FileUpdate, error) { entries, err := git.ParseTreeEntries(stdout) if err != nil { return nil, err @@ -76,7 +76,7 @@ func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) { updates[idxCount] = internal.FileUpdate{ Filename: entry.Name(), BlobSha: entry.ID.String(), - Size: entry.Size(), + Size: entry.GetSize(ctx, gitRepo), Sized: true, } idxCount++ @@ -86,7 +86,7 @@ func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) { } // genesisChanges get changes to add repo to the indexer for the first time -func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { +func genesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, revision string) (*internal.RepoChanges, error) { var changes internal.RepoChanges stdout, _, runErr := gitrepo.RunCmdBytes(ctx, repo, gitcmd.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision)) if runErr != nil { @@ -94,12 +94,12 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision s } var err error - changes.Updates, err = parseGitLsTreeOutput(stdout) + changes.Updates, err = parseGitLsTreeOutput(ctx, gitRepo, stdout) return &changes, err } // nonGenesisChanges get changes since the previous indexer update -func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { +func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, revision string) (*internal.RepoChanges, error) { diffCmd := gitcmd.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision) stdout, _, runErr := gitrepo.RunCmdString(ctx, repo, diffCmd) if runErr != nil { @@ -109,7 +109,7 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio if err := (*globalIndexer.Load()).Delete(ctx, repo.ID); err != nil { return nil, err } - return genesisChanges(ctx, repo, revision) + return genesisChanges(ctx, repo, gitRepo, revision) } var changes internal.RepoChanges @@ -124,7 +124,7 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio return err } - updates, err1 := parseGitLsTreeOutput(lsTreeStdout) + updates, err1 := parseGitLsTreeOutput(ctx, gitRepo, lsTreeStdout) if err1 != nil { return err1 } diff --git a/modules/indexer/code/indexer.go b/modules/indexer/code/indexer.go index 312b038e0ee..be067128157 100644 --- a/modules/indexer/code/indexer.go +++ b/modules/indexer/code/indexer.go @@ -13,6 +13,7 @@ import ( "gitea.dev/models/db" repo_model "gitea.dev/models/repo" + "gitea.dev/modules/gitrepo" "gitea.dev/modules/graceful" "gitea.dev/modules/indexer" "gitea.dev/modules/indexer/code/bleve" @@ -73,11 +74,17 @@ func index(ctx context.Context, indexer internal.Indexer, repoID int64) error { return nil } + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) + if err != nil { + return err + } + defer closer.Close() + sha, err := getDefaultBranchSha(ctx, repo) if err != nil { return err } - changes, err := getRepoChanges(ctx, repo, sha) + changes, err := getRepoChanges(ctx, repo, gitRepo, sha) if err != nil { return err } else if changes == nil { diff --git a/modules/indexer/stats/db.go b/modules/indexer/stats/db.go index af5127b6389..6544041f24e 100644 --- a/modules/indexer/stats/db.go +++ b/modules/indexer/stats/db.go @@ -63,7 +63,7 @@ func (db *DBIndexer) Index(id int64) error { } // Calculate and save language statistics to database - stats, err := languagestats.GetLanguageStats(gitRepo, commitID) + stats, err := languagestats.GetLanguageStats(ctx, gitRepo, commitID) if err != nil { if !setting.IsInTesting { log.Error("Unable to get language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.FullName(), err) diff --git a/modules/issue/template/unmarshal.go b/modules/issue/template/unmarshal.go index e0d6881cf59..eebf8c40b12 100644 --- a/modules/issue/template/unmarshal.go +++ b/modules/issue/template/unmarshal.go @@ -4,6 +4,7 @@ package template import ( + "context" "fmt" "path" "strconv" @@ -41,35 +42,35 @@ func Unmarshal(filename string, content []byte) (*api.IssueTemplate, error) { } // UnmarshalFromEntry parses out a valid template from the blob in entry -func UnmarshalFromEntry(entry *git.TreeEntry, dir string) (*api.IssueTemplate, error) { - return unmarshalFromEntry(entry, path.Join(dir, entry.Name())) // Filepaths in Git are ALWAYS '/' separated do not use filepath here +func UnmarshalFromEntry(gitRepo *git.Repository, entry *git.TreeEntry, dir string) (*api.IssueTemplate, error) { + return unmarshalFromEntry(gitRepo, entry, path.Join(dir, entry.Name())) // Filepaths in Git are ALWAYS '/' separated do not use filepath here } // UnmarshalFromCommit parses out a valid template from the commit -func UnmarshalFromCommit(commit *git.Commit, filename string) (*api.IssueTemplate, error) { - entry, err := commit.GetTreeEntryByPath(filename) +func UnmarshalFromCommit(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, filename string) (*api.IssueTemplate, error) { + entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, filename) if err != nil { return nil, fmt.Errorf("get entry for %q: %w", filename, err) } - return unmarshalFromEntry(entry, filename) + return unmarshalFromEntry(gitRepo, entry, filename) } // UnmarshalFromRepo parses out a valid template from the head commit of the branch -func UnmarshalFromRepo(repo *git.Repository, branch, filename string) (*api.IssueTemplate, error) { +func UnmarshalFromRepo(ctx context.Context, repo *git.Repository, branch, filename string) (*api.IssueTemplate, error) { commit, err := repo.GetBranchCommit(branch) if err != nil { return nil, fmt.Errorf("get commit on branch %q: %w", branch, err) } - return UnmarshalFromCommit(commit, filename) + return UnmarshalFromCommit(ctx, repo, commit, filename) } -func unmarshalFromEntry(entry *git.TreeEntry, filename string) (*api.IssueTemplate, error) { - if size := entry.Blob().Size(); size > setting.UI.MaxDisplayFileSize { +func unmarshalFromEntry(gitRepo *git.Repository, entry *git.TreeEntry, filename string) (*api.IssueTemplate, error) { + if size := entry.Blob(gitRepo).Size(); size > setting.UI.MaxDisplayFileSize { return nil, fmt.Errorf("too large: %v > MaxDisplayFileSize", size) } - r, err := entry.Blob().DataAsync() + r, err := entry.Blob(gitRepo).DataAsync() if err != nil { return nil, fmt.Errorf("data async: %w", err) } diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go index fb7d2986bb6..fa73e215b4e 100644 --- a/routers/api/v1/repo/commits.go +++ b/routers/api/v1/repo/commits.go @@ -235,7 +235,7 @@ func GetAllCommits(ctx *context.APIContext) { } // Query commits - commits, err = baseCommit.CommitsByRange(listOptions.Page, listOptions.PageSize, not, since, until) + commits, err = baseCommit.CommitsByRange(ctx.Repo.GitRepo, listOptions.Page, listOptions.PageSize, not, since, until) if err != nil { ctx.APIErrorInternal(err) return diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 5f10c4fbd71..cb659a9f940 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -202,7 +202,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) { } func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified *time.Time) { - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { if git.IsErrNotExist(err) { ctx.APIErrorNotFound() @@ -224,7 +224,7 @@ func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEn } when := &latestCommit.Committer.When - return entry.Blob(), entry, when + return entry.Blob(ctx.Repo.GitRepo), entry, when } // GetArchive get archive of a repository @@ -299,7 +299,7 @@ func GetEditorconfig(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - ec, _, err := ctx.Repo.GetEditorconfig(ctx.Repo.Commit) + ec, _, err := ctx.Repo.GetEditorconfig(ctx, ctx.Repo.Commit) if err != nil { ctx.APIErrorAuto(err) return diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 8adef610001..531b48fe76a 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -1200,7 +1200,7 @@ func GetIssueTemplates(ctx *context.APIContext) { // "$ref": "#/responses/IssueTemplates" // "404": // "$ref": "#/responses/notFound" - ret := issue.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + ret := issue.ParseTemplatesFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) if cnt := len(ret.TemplateErrors); cnt != 0 { ctx.Resp.Header().Add("X-Gitea-Warning", "error occurs when parsing issue template: count="+strconv.Itoa(cnt)) } @@ -1230,7 +1230,7 @@ func GetIssueConfig(ctx *context.APIContext) { // "$ref": "#/responses/RepoIssueConfig" // "404": // "$ref": "#/responses/notFound" - issueConfig, _ := issue.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + issueConfig, _ := issue.GetTemplateConfigFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) ctx.JSON(http.StatusOK, issueConfig) } @@ -1257,7 +1257,7 @@ func ValidateIssueConfig(ctx *context.APIContext) { // "$ref": "#/responses/RepoIssueConfigValidation" // "404": // "$ref": "#/responses/notFound" - _, err := issue.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + _, err := issue.GetTemplateConfigFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) if err == nil { ctx.JSON(http.StatusOK, api.IssueConfigValidation{Valid: true, Message: ""}) diff --git a/routers/api/v1/repo/tree.go b/routers/api/v1/repo/tree.go index 7c41a0e86d9..2514421ca69 100644 --- a/routers/api/v1/repo/tree.go +++ b/routers/api/v1/repo/tree.go @@ -62,7 +62,7 @@ func GetTree(ctx *context.APIContext) { return } if tree, err := files_service.GetTreeBySHA(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, sha, ctx.FormInt("page"), ctx.FormInt("per_page"), ctx.FormBool("recursive")); err != nil { - ctx.APIError(http.StatusBadRequest, err.Error()) + ctx.APIErrorAuto(err) } else { ctx.SetTotalCountHeader(int64(tree.TotalCount)) ctx.JSON(http.StatusOK, tree) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 67209fa1271..d771aac00a1 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -177,17 +177,17 @@ func getWikiPage(ctx *context.APIContext, wikiName wiki_service.WebPath) *api.Wi } // lookup filename in wiki - get filecontent, real filename - content, pageFilename := wikiContentsByName(ctx, commit, wikiName, false) + content, pageFilename := wikiContentsByName(ctx, wikiRepo, commit, wikiName, false) if ctx.Written() { return nil } - sidebarContent, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) + sidebarContent, _ := wikiContentsByName(ctx, wikiRepo, commit, "_Sidebar", true) if ctx.Written() { return nil } - footerContent, _ := wikiContentsByName(ctx, commit, "_Footer", true) + footerContent, _ := wikiContentsByName(ctx, wikiRepo, commit, "_Footer", true) if ctx.Written() { return nil } @@ -303,7 +303,7 @@ func ListWikiPages(ctx *context.APIContext) { skip := (page - 1) * limit maxNum := page * limit - entries, err := commit.ListEntries() + entries, err := commit.Tree().ListEntries(ctx, wikiRepo) if err != nil { ctx.APIErrorInternal(err) return @@ -420,7 +420,7 @@ func ListPageRevisions(ctx *context.APIContext) { } // lookup filename in wiki - get filecontent, gitTree entry , real filename - _, pageFilename := wikiContentsByName(ctx, commit, pageName, false) + _, pageFilename := wikiContentsByName(ctx, wikiRepo, commit, pageName, false) if ctx.Written() { return } @@ -448,8 +448,8 @@ func ListPageRevisions(ctx *context.APIContext) { } // findEntryForFile finds the tree entry for a target filepath. -func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) { - entry, err := commit.GetTreeEntryByPath(target) +func findEntryForFile(ctx *context.APIContext, wikiRepo *git.Repository, commit *git.Commit, target string) (*git.TreeEntry, error) { + entry, err := commit.GetTreeEntryByPath(ctx, wikiRepo, target) if err != nil { return nil, err } @@ -462,7 +462,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) if unescapedTarget, err = url.QueryUnescape(target); err != nil { return nil, err } - return commit.GetTreeEntryByPath(unescapedTarget) + return commit.GetTreeEntryByPath(ctx, wikiRepo, unescapedTarget) } // findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error. @@ -484,8 +484,8 @@ func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) // wikiContentsByEntry returns the contents of the wiki page referenced by the // given tree entry, encoded with base64. Writes to ctx if an error occurs. -func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) string { - blob := entry.Blob() +func wikiContentsByEntry(ctx *context.APIContext, wikiRepo *git.Repository, entry *git.TreeEntry) string { + blob := entry.Blob(wikiRepo) if blob.Size() > setting.API.DefaultMaxBlobSize { return "" } @@ -499,9 +499,9 @@ func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) string { // wikiContentsByName returns the contents of a wiki page, along with a boolean // indicating whether the page exists. Writes to ctx if an error occurs. -func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName wiki_service.WebPath, isSidebarOrFooter bool) (string, string) { +func wikiContentsByName(ctx *context.APIContext, wikiRepo *git.Repository, commit *git.Commit, wikiName wiki_service.WebPath, isSidebarOrFooter bool) (string, string) { gitFilename := wiki_service.WebPathToGitPath(wikiName) - entry, err := findEntryForFile(commit, gitFilename) + entry, err := findEntryForFile(ctx, wikiRepo, commit, gitFilename) if err != nil { if git.IsErrNotExist(err) { if !isSidebarOrFooter { @@ -512,5 +512,5 @@ func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName wi } return "", "" } - return wikiContentsByEntry(ctx, entry), gitFilename + return wikiContentsByEntry(ctx, wikiRepo, entry), gitFilename } diff --git a/routers/private/hook_verification.go b/routers/private/hook_verification.go index a21c12d4657..203b67fc3d8 100644 --- a/routers/private/hook_verification.go +++ b/routers/private/hook_verification.go @@ -64,7 +64,7 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error { return cmd.WithEnv(env). WithDir(repo.Path). WithPipelineFunc(func(ctx gitcmd.Context) error { - commit, err := git.CommitFromReader(repo, commitID, stdoutReader) + commit, err := git.CommitFromReader(commitID, stdoutReader) if err != nil { return err } diff --git a/routers/web/feed/branch.go b/routers/web/feed/branch.go index 139b7ebc430..58d57b60962 100644 --- a/routers/web/feed/branch.go +++ b/routers/web/feed/branch.go @@ -21,7 +21,7 @@ func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType stri var commits []*git.Commit var err error if ctx.Repo.Commit != nil { - commits, err = ctx.Repo.Commit.CommitsByRange(0, 10, "", "", "") + commits, err = ctx.Repo.Commit.CommitsByRange(ctx.Repo.GitRepo, 0, 10, "", "", "") if err != nil { ctx.ServerError("ShowBranchFeed", err) return diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index 7839ef31339..830cd25eb65 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -206,7 +206,7 @@ func WorkflowDispatchInputs(ctx *context.Context) { func prepareWorkflowTemplate(ctx *context.Context, commit *git.Commit) (workflows []WorkflowInfo, curWorkflowID string) { curWorkflowID = ctx.FormString("workflow") - _, entries, err := actions.ListWorkflows(commit) + _, entries, err := actions.ListWorkflows(ctx, ctx.Repo.GitRepo, commit) if err != nil { ctx.ServerError("ListWorkflows", err) return nil, "" @@ -215,7 +215,7 @@ func prepareWorkflowTemplate(ctx *context.Context, commit *git.Commit) (workflow workflows = make([]WorkflowInfo, 0, len(entries)) for _, entry := range entries { workflow := WorkflowInfo{EntryName: entry.Name()} - content, err := actions.GetContentFromEntry(entry) + content, err := actions.GetContentFromEntry(ctx.Repo.GitRepo, entry) if err != nil { ctx.ServerError("GetContentFromEntry", err) return nil, "" diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 5bf5353d30c..d5035099de5 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -257,7 +257,7 @@ func ViewWorkflowFile(ctx *context_module.Context) { }, err) return } - rpath, entries, err := actions.ListWorkflows(commit) + rpath, entries, err := actions.ListWorkflows(ctx, ctx.Repo.GitRepo, commit) if err != nil { ctx.ServerError("ListWorkflows", err) return @@ -1414,7 +1414,7 @@ func viewScopedWorkflowFile(ctx *context_module.Context, run *actions_model.Acti }, err) return } - rpath, entries, err := actions.ListScopedWorkflows(commit) + rpath, entries, err := actions.ListScopedWorkflows(ctx, sourceGitRepo, commit) if err != nil { ctx.ServerError("ListScopedWorkflows", err) return diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index 457f9795a23..0bc8cfc2aed 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -13,7 +13,6 @@ import ( "strconv" "gitea.dev/models/gituser" - repo_model "gitea.dev/models/repo" "gitea.dev/modules/charset" "gitea.dev/modules/git" "gitea.dev/modules/git/languagestats" @@ -51,13 +50,13 @@ func RefBlame(ctx *context.Context) { ctx.NotFound(nil) return } - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return } - blob := entry.Blob() + blob := entry.Blob(ctx.Repo.GitRepo) fileSize := blob.Size() ctx.Data["FileSize"] = fileSize ctx.Data["FileTreePath"] = ctx.Repo.TreePath @@ -81,7 +80,7 @@ func RefBlame(ctx *context.Context) { } bypassBlameIgnore, _ := strconv.ParseBool(ctx.FormString("bypass-blame-ignore")) - result, err := performBlame(ctx, ctx.Repo.Repository, ctx.Repo.Commit, ctx.Repo.TreePath, bypassBlameIgnore) + result, err := performBlame(ctx, bypassBlameIgnore) if err != nil { ctx.NotFound(err) return @@ -106,10 +105,14 @@ type blameResult struct { FaultyIgnoreRevsFile bool } -func performBlame(ctx *context.Context, repo *repo_model.Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (*blameResult, error) { +func performBlame(ctx *context.Context, bypassBlameIgnore bool) (*blameResult, error) { + repo := ctx.Repo.Repository + gitRepo := ctx.Repo.GitRepo + commit := ctx.Repo.Commit + file := ctx.Repo.TreePath objectFormat := ctx.Repo.GetObjectFormat() - blameReader, err := gitrepo.CreateBlameReader(ctx, objectFormat, repo, commit, file, bypassBlameIgnore) + blameReader, err := gitrepo.CreateBlameReader(ctx, objectFormat, repo, gitRepo, commit, file, bypassBlameIgnore) if err != nil { return nil, err } @@ -125,7 +128,7 @@ func performBlame(ctx *context.Context, repo *repo_model.Repository, commit *git if len(r.Parts) == 0 && r.UsesIgnoreRevs { // try again without ignored revs - blameReader, err = gitrepo.CreateBlameReader(ctx, objectFormat, repo, commit, file, true) + blameReader, err = gitrepo.CreateBlameReader(ctx, objectFormat, repo, gitRepo, commit, file, true) if err != nil { return nil, err } diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index b1b1909e10c..4630337b59c 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -76,7 +76,7 @@ func Commits(ctx *context.Context) { } // Both `git log branchName` and `git log commitId` work. - commits, err := ctx.Repo.Commit.CommitsByRange(page, pageSize, "", "", "") + commits, err := ctx.Repo.Commit.CommitsByRange(ctx.Repo.GitRepo, page, pageSize, "", "", "") if err != nil { ctx.ServerError("CommitsByRange", err) return @@ -189,7 +189,7 @@ func SearchCommits(ctx *context.Context) { all := ctx.FormBool("all") opts := git.NewSearchCommitsOptions(query, all) - commits, err := ctx.Repo.Commit.SearchCommits(opts) + commits, err := ctx.Repo.Commit.SearchCommits(ctx.Repo.GitRepo, opts) if err != nil { ctx.ServerError("SearchCommits", err) return diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index dd00be2da28..fb7b07293a1 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -61,7 +61,7 @@ func setCompareContext(ctx *context.Context, before, head *git.Commit, headOwner return nil } - blob, err := commit.GetBlobByPath(path) + blob, err := commit.GetBlobByPath(ctx, ctx.Repo.GitRepo, path) if err != nil { return nil } @@ -773,7 +773,7 @@ func ExcerptBlob(ctx *context.Context) { ctx.ServerError("GetCommit", err) return } - blob, err := commit.Tree.GetBlobByPath(filePath) + blob, err := commit.GetBlobByPath(ctx, ctx.Repo.GitRepo, filePath) if err != nil { ctx.ServerError("GetBlobByPath", err) return diff --git a/routers/web/repo/download.go b/routers/web/repo/download.go index e92e44532a9..0f20b5c0b70 100644 --- a/routers/web/repo/download.go +++ b/routers/web/repo/download.go @@ -67,7 +67,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified *time.Tim } func getBlobForEntry(ctx *context.Context) (*git.Blob, *time.Time) { - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { if git.IsErrNotExist(err) { ctx.NotFound(err) @@ -89,7 +89,7 @@ func getBlobForEntry(ctx *context.Context) (*git.Blob, *time.Time) { } lastModified := &latestCommit.Committer.When - return entry.Blob(), lastModified + return entry.Blob(ctx.Repo.GitRepo), lastModified } // SingleDownload download a file by repos path diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 95928d87032..187ed837feb 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -224,7 +224,7 @@ func redirectForCommitChoice[T any](ctx *context.Context, parsed *preparedEditor } func editFileOpenExisting(ctx *context.Context) (prefetch []byte, dataRc io.ReadCloser, fInfo *fileInfo) { - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { HandleGitError(ctx, "GetTreeEntryByPath", err) return nil, nil, nil @@ -236,7 +236,7 @@ func editFileOpenExisting(ctx *context.Context) (prefetch []byte, dataRc io.Read return nil, nil, nil } - blob := entry.Blob() + blob := entry.Blob(ctx.Repo.GitRepo) buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, blob) if err != nil { if git.IsErrNotExist(err) { @@ -403,7 +403,7 @@ func DeleteFilePost(ctx *context.Context) { } // Check if the path is a directory - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, treePath) if err != nil { ctx.NotFoundOrServerError("GetTreeEntryByPath", git.IsErrNotExist, err) return @@ -442,7 +442,7 @@ func DeleteFilePost(ctx *context.Context) { } else { ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", treePath)) } - redirectTreePath := getClosestParentWithFiles(ctx.Repo.GitRepo, parsed.NewBranchName, treePath) + redirectTreePath := getClosestParentWithFiles(ctx, ctx.Repo.GitRepo, parsed.NewBranchName, treePath) redirectForCommitChoice(ctx, parsed, redirectTreePath) } diff --git a/routers/web/repo/editor_preview.go b/routers/web/repo/editor_preview.go index 5fc0d38ccab..8817f792cf2 100644 --- a/routers/web/repo/editor_preview.go +++ b/routers/web/repo/editor_preview.go @@ -19,7 +19,7 @@ func DiffPreviewPost(ctx *context.Context) { return } - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, treePath) if err != nil { ctx.ServerError("GetTreeEntryByPath", err) return @@ -28,7 +28,7 @@ func DiffPreviewPost(ctx *context.Context) { return } - oldContent, err := entry.Blob().GetBlobContent(setting.UI.MaxDisplayFileSize) + oldContent, err := entry.Blob(ctx.Repo.GitRepo).GetBlobContent(setting.UI.MaxDisplayFileSize) if err != nil { ctx.ServerError("GetBlobContent", err) return diff --git a/routers/web/repo/editor_test.go b/routers/web/repo/editor_test.go index 73fc92e8a12..1706ab670e9 100644 --- a/routers/web/repo/editor_test.go +++ b/routers/web/repo/editor_test.go @@ -23,9 +23,9 @@ func TestEditorUtils(t *testing.T) { t.Run("getClosestParentWithFiles", func(t *testing.T) { gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo) defer gitRepo.Close() - treePath := getClosestParentWithFiles(gitRepo, "sub-home-md-img-check", "docs/foo/bar") + treePath := getClosestParentWithFiles(t.Context(), gitRepo, "sub-home-md-img-check", "docs/foo/bar") assert.Equal(t, "docs", treePath) - treePath = getClosestParentWithFiles(gitRepo, "sub-home-md-img-check", "any/other") + treePath = getClosestParentWithFiles(t.Context(), gitRepo, "sub-home-md-img-check", "any/other") assert.Empty(t, treePath) }) } diff --git a/routers/web/repo/editor_util.go b/routers/web/repo/editor_util.go index c23eee18fcd..bc32b6ed996 100644 --- a/routers/web/repo/editor_util.go +++ b/routers/web/repo/editor_util.go @@ -43,16 +43,16 @@ func getUniquePatchBranchName(ctx context.Context, prefixName string, repo *repo // getClosestParentWithFiles Recursively gets the closest path of parent in a tree that has files when a file in a tree is // deleted. It returns "" for the tree root if no parents other than the root have files. -func getClosestParentWithFiles(gitRepo *git.Repository, branchName, originTreePath string) string { +func getClosestParentWithFiles(ctx context.Context, gitRepo *git.Repository, branchName, originTreePath string) string { var f func(treePath string, commit *git.Commit) string f = func(treePath string, commit *git.Commit) string { if treePath == "" || treePath == "." { return "" } // see if the tree has entries - if tree, err := commit.SubTree(treePath); err != nil { + if tree, err := commit.SubTree(ctx, gitRepo, treePath); err != nil { return f(path.Dir(treePath), commit) // failed to get the tree, going up a dir - } else if entries, err := tree.ListEntries(); err != nil || len(entries) == 0 { + } else if entries, err := tree.ListEntries(ctx, gitRepo); err != nil || len(entries) == 0 { return f(path.Dir(treePath), commit) // no files in this dir, going up a dir } return treePath @@ -87,7 +87,7 @@ func getCodeEditorConfigByEditorconfig(ctx *context_service.Context, treePath st ret.LineWrapExtensions = setting.Repository.Editor.LineWrapExtensions ret.LineWrap = util.SliceContainsString(ret.LineWrapExtensions, path.Ext(treePath), true) ret.Previewable = util.SliceContainsString(ret.PreviewableExtensions, path.Ext(treePath), true) - ec, _, err := ctx.Repo.GetEditorconfig() + ec, _, err := ctx.Repo.GetEditorconfig(ctx) if err == nil { def, err := ec.GetDefinitionForFilename(treePath) if err == nil { diff --git a/routers/web/repo/issue_list.go b/routers/web/repo/issue_list.go index 5ccef292a20..9bdc6822f2e 100644 --- a/routers/web/repo/issue_list.go +++ b/routers/web/repo/issue_list.go @@ -754,7 +754,7 @@ func Issues(ctx *context.Context) { } ctx.Data["Title"] = ctx.Tr("repo.issues") ctx.Data["PageIsIssueList"] = true - ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo) + ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) } projectIDs := parseProjectIDsFromQuery(ctx) diff --git a/routers/web/repo/issue_new.go b/routers/web/repo/issue_new.go index 57786dd7d7a..d108ca86c88 100644 --- a/routers/web/repo/issue_new.go +++ b/routers/web/repo/issue_new.go @@ -51,10 +51,10 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles templateErrs := map[string]error{} for _, filename := range templateCandidates { - if ok, _ := commit.HasFile(filename); !ok { + template, err := issue_template.UnmarshalFromCommit(ctx, ctx.Repo.GitRepo, commit, filename) + if errors.Is(err, util.ErrNotExist) { continue } - template, err := issue_template.UnmarshalFromCommit(commit, filename) if err != nil { templateErrs[filename] = err continue @@ -98,8 +98,8 @@ func setTemplateIfExists(ctx *context.Context, ctxDataKey string, possibleFiles // NewIssue render creating issue page func NewIssue(ctx *context.Context) { - issueConfig, _ := issue_service.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) - hasTemplates := issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo) + issueConfig, _ := issue_service.GetTemplateConfigFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) + hasTemplates := issue_service.HasTemplatesOrContactLinks(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) ctx.Data["Title"] = ctx.Tr("repo.issues.new") ctx.Data["PageIsIssueList"] = true @@ -134,7 +134,7 @@ func NewIssue(ctx *context.Context) { } ctx.Data["Tags"] = tags - ret := issue_service.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + ret := issue_service.ParseTemplatesFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) templateLoaded, errs := setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates, pageMetaData) maps.Copy(ret.TemplateErrors, errs) if ctx.Written() { @@ -186,20 +186,20 @@ func NewIssueChooseTemplate(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.issues.new") ctx.Data["PageIsIssueList"] = true - ret := issue_service.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + ret := issue_service.ParseTemplatesFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) ctx.Data["IssueTemplates"] = ret.IssueTemplates if len(ret.TemplateErrors) > 0 { ctx.Flash.Warning(renderErrorOfTemplates(ctx, ret.TemplateErrors), true) } - if !issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo) { + if !issue_service.HasTemplatesOrContactLinks(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) { // The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters. ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.Link(), ctx.Req.URL.RawQuery), http.StatusSeeOther) return } - issueConfig, err := issue_service.GetTemplateConfigFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + issueConfig, err := issue_service.GetTemplateConfigFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) ctx.Data["IssueConfig"] = issueConfig ctx.Data["IssueConfigError"] = err // ctx.Flash.Err makes problems here @@ -358,7 +358,7 @@ func NewIssuePost(ctx *context.Context) { content := form.Content if filename := ctx.Req.Form.Get("template-file"); filename != "" { - if template, err := issue_template.UnmarshalFromRepo(ctx.Repo.GitRepo, ctx.Repo.Repository.DefaultBranch, filename); err == nil { + if template, err := issue_template.UnmarshalFromRepo(ctx, ctx.Repo.GitRepo, ctx.Repo.Repository.DefaultBranch, filename); err == nil { content = issue_template.RenderToMarkdown(template, ctx.Req.Form) } } diff --git a/routers/web/repo/issue_view.go b/routers/web/repo/issue_view.go index a5bed6bba05..6b97f1b0cd3 100644 --- a/routers/web/repo/issue_view.go +++ b/routers/web/repo/issue_view.go @@ -334,7 +334,7 @@ func ViewIssue(ctx *context.Context) { return } ctx.Data["PageIsIssueList"] = true - ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo) + ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) } ctx.Data["IsProjectsEnabled"] = ctx.Repo.Permission.CanRead(unit.TypeProjects) diff --git a/routers/web/repo/middlewares.go b/routers/web/repo/middlewares.go index 8ae99fbbb74..a4c0fac551e 100644 --- a/routers/web/repo/middlewares.go +++ b/routers/web/repo/middlewares.go @@ -22,7 +22,7 @@ func SetEditorconfigIfExists(ctx *context.Context) { return } - ec, _, err := ctx.Repo.GetEditorconfig() + ec, _, err := ctx.Repo.GetEditorconfig(ctx) if err != nil { // it used to check `!git.IsErrNotExist(err)` and create a system notice, but it is quite annoying and useless // because network errors also happen frequently, so we just ignore it diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go index ad3a71804c8..c639754dc8e 100644 --- a/routers/web/repo/milestone.go +++ b/routers/web/repo/milestone.go @@ -262,7 +262,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) { prepareIssueFilterAndList(ctx, milestoneID, projectIDs, optional.None[bool]()) - ret := issue.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) + ret := issue.ParseTemplatesFromDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo) ctx.Data["NewIssueChooseTemplate"] = len(ret.IssueTemplates) > 0 ctx.Data["CanWriteIssues"] = ctx.Repo.Permission.CanWriteIssuesOrPulls(false) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 62b956d06cd..c24e24211ff 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -744,7 +744,7 @@ func viewPullFiles(ctx *context.Context, beforeCommitID, afterCommitID string) { var beforeCommit *git.Commit if isSingleCommit { - beforeCommit, err = afterCommit.Parent(0) + beforeCommit, err = afterCommit.Parent(ctx.Repo.GitRepo, 0) if err != nil { ctx.ServerError("afterCommit.Parent", err) return @@ -1377,7 +1377,7 @@ func CompareAndPullRequestPost(ctx *context.Context) { content := form.Content if filename := ctx.Req.Form.Get("template-file"); filename != "" { - if template, err := issue_template.UnmarshalFromRepo(ctx.Repo.GitRepo, ctx.Repo.Repository.DefaultBranch, filename); err == nil { + if template, err := issue_template.UnmarshalFromRepo(ctx, ctx.Repo.GitRepo, ctx.Repo.Repository.DefaultBranch, filename); err == nil { content = issue_template.RenderToMarkdown(template, ctx.Req.Form) } } diff --git a/routers/web/repo/render.go b/routers/web/repo/render.go index b323da163c0..254b9a15c78 100644 --- a/routers/web/repo/render.go +++ b/routers/web/repo/render.go @@ -19,7 +19,7 @@ func RenderFile(ctx *context.Context) { var blob *git.Blob var err error if ctx.Repo.TreePath != "" { - blob, err = ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath) + blob, err = ctx.Repo.Commit.GetBlobByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) } else { blob, err = ctx.Repo.GitRepo.GetBlob(ctx.PathParam("sha")) } diff --git a/routers/web/repo/treelist.go b/routers/web/repo/treelist.go index 45889cbe5df..206660ad5c7 100644 --- a/routers/web/repo/treelist.go +++ b/routers/web/repo/treelist.go @@ -22,13 +22,13 @@ import ( // TreeList get all files' entries of a repository func TreeList(ctx *context.Context) { - tree, err := ctx.Repo.Commit.SubTree("/") + tree, err := ctx.Repo.Commit.SubTree(ctx, ctx.Repo.GitRepo, "/") if err != nil { ctx.ServerError("Repo.Commit.SubTree", err) return } - entries, err := tree.ListEntriesRecursiveFast() + entries, err := tree.ListEntriesRecursiveFast(ctx, ctx.Repo.GitRepo) if err != nil { ctx.ServerError("ListEntriesRecursiveFast", err) return @@ -144,7 +144,7 @@ func transformDiffTreeForWeb(renderedIconPool *fileicon.RenderedIconPool, diffTr func TreeViewNodes(ctx *context.Context) { renderedIconPool := fileicon.NewRenderedIconPool() - results, err := files_service.GetTreeViewNodes(ctx, ctx.Repo.RepoLink, renderedIconPool, ctx.Repo.Commit, ctx.Repo.TreePath, ctx.FormString("sub_path")) + results, err := files_service.GetTreeViewNodes(ctx, ctx.Repo.RepoLink, renderedIconPool, ctx.Repo.GitRepo, ctx.Repo.Commit, ctx.Repo.TreePath, ctx.FormString("sub_path")) if err != nil { ctx.ServerError("GetTreeViewNodes", err) return diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 6df4e738c99..f976034e34c 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -260,7 +260,7 @@ func prepareDirectoryFileIcons(ctx *context.Context, files []git.CommitInfo) { fileIcons := map[string]template.HTML{} for _, f := range files { fullPath := path.Join(ctx.Repo.TreePath, f.Entry.Name()) - entryInfo := fileicon.EntryInfoFromGitTreeEntry(ctx.Repo.Commit, fullPath, f.Entry) + entryInfo := fileicon.EntryInfoFromGitTreeEntry(ctx, ctx.Repo.GitRepo, ctx.Repo.Commit, fullPath, f.Entry) fileIcons[f.Entry.Name()] = fileicon.RenderEntryIconHTML(renderedIconPool, entryInfo) } fileIcons[".."] = fileicon.RenderEntryIconHTML(renderedIconPool, fileicon.EntryInfoFolder()) @@ -269,7 +269,7 @@ func prepareDirectoryFileIcons(ctx *context.Context, files []git.CommitInfo) { } func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entries { - tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath) + tree, err := ctx.Repo.Commit.SubTree(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { HandleGitError(ctx, "Repo.Commit.SubTree", err) return nil @@ -280,7 +280,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri ctx.Data["LastCommitLoaderURL"] = lastCommitLoaderURL + "?refSubUrl=" + url.QueryEscape(ctx.Repo.RefTypeNameSubURL()) // Get current entry user currently looking at. - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return nil @@ -291,7 +291,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri return nil } - allEntries, err := tree.ListEntries() + allEntries, err := tree.ListEntries(ctx, ctx.Repo.GitRepo) if err != nil { ctx.ServerError("ListEntries", err) return nil @@ -305,7 +305,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri defer cancel() } - files, latestCommit, err := allEntries.GetCommitsInfo(commitInfoCtx, ctx.Repo.RepoLink, ctx.Repo.Commit, ctx.Repo.TreePath) + files, latestCommit, err := allEntries.GetCommitsInfo(commitInfoCtx, ctx.Repo.RepoLink, ctx.Repo.GitRepo, ctx.Repo.Commit, ctx.Repo.TreePath) if err != nil { ctx.ServerError("GetCommitsInfo", err) return nil @@ -328,6 +328,9 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri } ctx.Data["Files"] = files + ctx.Data["GetSubJumpablePathName"] = func(entry *git.TreeEntry) string { + return entry.GetSubJumpablePathName(ctx, ctx.Repo.GitRepo) + } prepareDirectoryFileIcons(ctx, files) for _, f := range files { if f.Commit == nil { diff --git a/routers/web/repo/view_file.go b/routers/web/repo/view_file.go index 6bbfc0cdeb0..336846dce7f 100644 --- a/routers/web/repo/view_file.go +++ b/routers/web/repo/view_file.go @@ -29,7 +29,7 @@ import ( ) func prepareLatestCommitInfo(ctx *context.Context) bool { - commit, err := ctx.Repo.Commit.GetCommitByPath(ctx.Repo.TreePath) + commit, err := ctx.Repo.Commit.GetCommitByPath(ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { ctx.ServerError("GetCommitByPath", err) return false @@ -161,7 +161,7 @@ func prepareFileView(ctx *context.Context, entry *git.TreeEntry) { return } - blob := entry.Blob() + blob := entry.Blob(ctx.Repo.GitRepo) ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+ctx.Repo.TreePath, ctx.Repo.RefFullName.ShortName()) ctx.Data["FileIsSymlink"] = entry.IsLink() @@ -169,7 +169,7 @@ func prepareFileView(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["RawFileLink"] = ctx.Repo.RepoLink + "/raw/" + ctx.Repo.RefTypeNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath) if ctx.Repo.TreePath == ".editorconfig" { - _, editorconfigWarning, editorconfigErr := ctx.Repo.GetEditorconfig(ctx.Repo.Commit) + _, editorconfigWarning, editorconfigErr := ctx.Repo.GetEditorconfig(ctx, ctx.Repo.Commit) if editorconfigWarning != nil { ctx.Data["FileWarning"] = strings.TrimSpace(editorconfigWarning.Error()) } @@ -177,12 +177,12 @@ func prepareFileView(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["FileError"] = strings.TrimSpace(editorconfigErr.Error()) } } else if issue_service.IsTemplateConfig(ctx.Repo.TreePath) { - _, issueConfigErr := issue_service.GetTemplateConfig(ctx.Repo.GitRepo, ctx.Repo.TreePath, ctx.Repo.Commit) + _, issueConfigErr := issue_service.GetTemplateConfig(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath, ctx.Repo.Commit) if issueConfigErr != nil { ctx.Data["FileError"] = strings.TrimSpace(issueConfigErr.Error()) } } else if actions.IsWorkflow(ctx.Repo.TreePath) { - content, err := actions.GetContentFromEntry(entry) + content, err := actions.GetContentFromEntry(ctx.Repo.GitRepo, entry) if err != nil { log.Error("actions.GetContentFromEntry: %v", err) } diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go index c570a8bb308..fa20a7261ac 100644 --- a/routers/web/repo/view_home.go +++ b/routers/web/repo/view_home.go @@ -100,12 +100,12 @@ func prepareHomeSidebarCitationFile(entry *git.TreeEntry) func(ctx *context.Cont if entry.Name() != "" { return } - tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath) + tree, err := ctx.Repo.Commit.SubTree(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { HandleGitError(ctx, "Repo.Commit.SubTree", err) return } - allEntries, err := tree.ListEntries() + allEntries, err := tree.ListEntries(ctx, ctx.Repo.GitRepo) if err != nil { ctx.ServerError("ListEntries", err) return @@ -113,7 +113,7 @@ func prepareHomeSidebarCitationFile(entry *git.TreeEntry) func(ctx *context.Cont for _, entry := range allEntries { if entry.Name() == "CITATION.cff" || entry.Name() == "CITATION.bib" { // Read Citation file contents - if content, err := entry.Blob().GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil { + if content, err := entry.Blob(ctx.Repo.GitRepo).GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil { log.Error("checkCitationFile: GetBlobContent: %v", err) } else { ctx.Data["CitiationExist"] = true @@ -290,7 +290,7 @@ func handleRepoViewSubmodule(ctx *context.Context, commitSubmoduleFile *git.Comm func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) { return func(ctx *context.Context) { if entry.IsSubModule() { - commitSubmoduleFile, err := git.GetCommitInfoSubmoduleFile(ctx.Repo.RepoLink, ctx.Repo.TreePath, ctx.Repo.Commit, entry.ID) + commitSubmoduleFile, err := git.GetCommitInfoSubmoduleFile(ctx, ctx.Repo.RepoLink, ctx.Repo.TreePath, ctx.Repo.GitRepo, ctx.Repo.Commit, entry.ID) if err != nil { HandleGitError(ctx, "prepareToRenderDirOrFile: GetCommitInfoSubmoduleFile", err) return @@ -351,7 +351,7 @@ func redirectFollowSymlink(ctx *context.Context, treePathEntry *git.TreeEntry) b return false } if treePathEntry.IsLink() { - if res, err := git.EntryFollowLinks(ctx.Repo.Commit, ctx.Repo.TreePath, treePathEntry); err == nil { + if res, err := git.EntryFollowLinks(ctx, ctx.Repo.GitRepo, ctx.Repo.Commit, ctx.Repo.TreePath, treePathEntry); err == nil { redirect := ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL() + "/" + util.PathEscapeSegments(res.TargetFullPath) + "?" + ctx.Req.URL.RawQuery ctx.Redirect(redirect) return true @@ -425,7 +425,7 @@ func Home(ctx *context.Context) { prepareHomeTreeSideBarSwitch(ctx) // get the current git entry which doer user is currently looking at. - entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) + entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx, ctx.Repo.GitRepo, ctx.Repo.TreePath) if err != nil { HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return diff --git a/routers/web/repo/view_readme.go b/routers/web/repo/view_readme.go index 2e50755d4f7..b045c51e5a1 100644 --- a/routers/web/repo/view_readme.go +++ b/routers/web/repo/view_readme.go @@ -66,9 +66,9 @@ func findReadmeFileInEntries(ctx *context.Context, parentDir string, entries []* for _, entry := range entries { if i, ok := util.IsReadmeFileExtension(entry.Name(), exts...); ok { fullPath := path.Join(parentDir, entry.Name()) - if readmeFiles[i] == nil || base.NaturalSortCompare(readmeFiles[i].Name(), entry.Blob().Name()) < 0 { + if readmeFiles[i] == nil || base.NaturalSortCompare(readmeFiles[i].Name(), entry.Blob(ctx.Repo.GitRepo).Name()) < 0 { if entry.IsLink() { - res, err := git.EntryFollowLinks(ctx.Repo.Commit, fullPath, entry) + res, err := git.EntryFollowLinks(ctx, ctx.Repo.GitRepo, ctx.Repo.Commit, fullPath, entry) if err == nil && (res.TargetEntry.IsExecutable() || res.TargetEntry.IsRegular()) { readmeFiles[i] = entry } @@ -92,12 +92,12 @@ func findReadmeFileInEntries(ctx *context.Context, parentDir string, entries []* if subTreeEntry == nil { continue } - subTree := subTreeEntry.Tree() + subTree := subTreeEntry.Tree(ctx.Repo.GitRepo) if subTree == nil { // this should be impossible; if subTreeEntry exists so should this. continue } - childEntries, err := subTree.ListEntries() + childEntries, err := subTree.ListEntries(ctx, ctx.Repo.GitRepo) if err != nil { return "", nil, err } @@ -145,7 +145,7 @@ func prepareToRenderReadmeFile(ctx *context.Context, subfolder string, readmeFil readmeFullPath := path.Join(ctx.Repo.TreePath, subfolder, readmeFile.Name()) readmeTargetEntry := readmeFile if readmeFile.IsLink() { - if res, err := git.EntryFollowLinks(ctx.Repo.Commit, readmeFullPath, readmeFile); err == nil { + if res, err := git.EntryFollowLinks(ctx, ctx.Repo.GitRepo, ctx.Repo.Commit, readmeFullPath, readmeFile); err == nil { readmeTargetEntry = res.TargetEntry } else { readmeTargetEntry = nil // if we cannot resolve the symlink, we cannot render the readme, ignore the error @@ -160,7 +160,7 @@ func prepareToRenderReadmeFile(ctx *context.Context, subfolder string, readmeFil ctx.Data["ReadmeExist"] = true ctx.Data["FileIsSymlink"] = readmeFile.IsLink() - buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, readmeTargetEntry.Blob()) + buf, dataRc, fInfo, err := getFileReader(ctx, ctx.Repo.Repository.ID, readmeTargetEntry.Blob(ctx.Repo.GitRepo)) if err != nil { ctx.ServerError("getFileReader", err) return diff --git a/routers/web/repo/view_readme_test.go b/routers/web/repo/view_readme_test.go index 43bee26450e..79b00ee7701 100644 --- a/routers/web/repo/view_readme_test.go +++ b/routers/web/repo/view_readme_test.go @@ -48,11 +48,12 @@ data 12 commit, err := gitRepo.GetBranchCommit("master") require.NoError(t, err) - entries, err := commit.ListEntries() + entries, err := commit.Tree().ListEntries(t.Context(), gitRepo) require.NoError(t, err) ctx, _ := contexttest.MockContext(t, "/") ctx.Repo.Commit = commit + ctx.Repo.GitRepo = gitRepo foundDir, foundReadme, err := findReadmeFileInEntries(ctx, "", entries, true) require.NoError(t, err) require.NotNil(t, foundReadme) @@ -62,7 +63,7 @@ data 12 assert.True(t, foundReadme.IsLink()) // Verify that it can follow the link - res, err := git.EntryFollowLinks(commit, path.Join(foundDir, foundReadme.Name()), foundReadme) + res, err := git.EntryFollowLinks(t.Context(), gitRepo, commit, path.Join(foundDir, foundReadme.Name()), foundReadme) require.NoError(t, err) assert.Equal(t, "target.md", res.TargetFullPath) }) diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 6e2133a9452..b3e2c2a2aa4 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -6,6 +6,7 @@ package repo import ( "bytes" + gocontext "context" "html/template" "io" "net/http" @@ -78,8 +79,8 @@ type PageMeta struct { } // findEntryForFile finds the tree entry for a target filepath. -func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) { - entry, err := commit.GetTreeEntryByPath(target) +func findEntryForFile(ctx gocontext.Context, wikiRepo *git.Repository, commit *git.Commit, target string) (*git.TreeEntry, error) { + entry, err := commit.GetTreeEntryByPath(ctx, wikiRepo, target) if err != nil && !git.IsErrNotExist(err) { return nil, err } @@ -92,7 +93,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) if unescapedTarget, err = url.QueryUnescape(target); err != nil { return nil, err } - return commit.GetTreeEntryByPath(unescapedTarget) + return commit.GetTreeEntryByPath(ctx, wikiRepo, unescapedTarget) } func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) { @@ -126,8 +127,8 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err // wikiContentsByEntry returns the contents of the wiki page referenced by the // given tree entry. Writes to ctx if an error occurs. -func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte { - reader, err := entry.Blob().DataAsync() +func wikiContentsByEntry(ctx *context.Context, wikiRepo *git.Repository, entry *git.TreeEntry) []byte { + reader, err := entry.Blob(wikiRepo).DataAsync() if err != nil { ctx.ServerError("Blob.Data", err) return nil @@ -144,10 +145,10 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte { // wikiEntryByName returns the entry of a wiki page, along with a boolean // indicating whether the entry exists. Writes to ctx if an error occurs. // The last return value indicates whether the file should be returned as a raw file -func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) { +func wikiEntryByName(ctx *context.Context, wikiRepo *git.Repository, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) { isRaw := false gitFilename := wiki_service.WebPathToGitPath(wikiName) - entry, err := findEntryForFile(commit, gitFilename) + entry, err := findEntryForFile(ctx, wikiRepo, commit, gitFilename) if err != nil && !git.IsErrNotExist(err) { ctx.ServerError("findEntryForFile", err) return nil, "", false, false @@ -155,7 +156,7 @@ func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_ser if entry == nil { // check if the file without ".md" suffix exists gitFilename := strings.TrimSuffix(gitFilename, ".md") - entry, err = findEntryForFile(commit, gitFilename) + entry, err = findEntryForFile(ctx, wikiRepo, commit, gitFilename) if err != nil && !git.IsErrNotExist(err) { ctx.ServerError("findEntryForFile", err) return nil, "", false, false @@ -170,12 +171,12 @@ func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_ser // wikiContentsByName returns the contents of a wiki page, along with a boolean // indicating whether the page exists. Writes to ctx if an error occurs. -func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) { - entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, commit, wikiName) +func wikiContentsByName(ctx *context.Context, wikiRepo *git.Repository, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) { + entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, wikiRepo, commit, wikiName) if entry == nil { return nil, nil, "", true } - return wikiContentsByEntry(ctx, entry), entry, gitFilename, noEntry + return wikiContentsByEntry(ctx, wikiRepo, entry), entry, gitFilename, noEntry } func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { @@ -188,7 +189,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { } // get the wiki pages list. - entries, err := commit.ListEntries() + entries, err := commit.Tree().ListEntries(ctx, wikiGitRepo) if err != nil { ctx.ServerError("ListEntries", err) return nil, nil @@ -233,7 +234,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { isFooter := pageName == "_Footer" // lookup filename in wiki - get gitTree entry , real filename - entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName) + entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, wikiGitRepo, commit, pageName) if noEntry { ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages") } @@ -245,7 +246,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { } // get page content - data := wikiContentsByEntry(ctx, entry) + data := wikiContentsByEntry(ctx, wikiGitRepo, entry) if ctx.Written() { return nil, nil } @@ -283,7 +284,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { } if !isSideBar { - sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar") + sidebarContent, _, _, _ := wikiContentsByName(ctx, wikiGitRepo, commit, "_Sidebar") if ctx.Written() { return nil, nil } @@ -295,7 +296,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { } if !isFooter { - footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer") + footerContent, _, _, _ := wikiContentsByName(ctx, wikiGitRepo, commit, "_Footer") if ctx.Written() { return nil, nil } @@ -335,7 +336,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) ctx.Data["title"] = displayName // lookup filename in wiki - get page content, gitTree entry , real filename - _, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) + _, entry, pageFilename, noEntry := wikiContentsByName(ctx, wikiGitRepo, commit, pageName) if noEntry { ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages") } @@ -375,7 +376,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) } func renderEditPage(ctx *context.Context) { - _, commit, err := findWikiRepoCommit(ctx) + wikiGitRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { if !git.IsErrNotExist(err) { ctx.ServerError("GetBranchCommit", err) @@ -396,7 +397,7 @@ func renderEditPage(ctx *context.Context) { ctx.Data["title"] = displayName // lookup filename in wiki - gitTree entry , real filename - entry, _, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName) + entry, _, noEntry, isRaw := wikiEntryByName(ctx, wikiGitRepo, commit, pageName) if noEntry { ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages") } @@ -408,7 +409,7 @@ func renderEditPage(ctx *context.Context) { } // get wiki page content - data := wikiContentsByEntry(ctx, entry) + data := wikiContentsByEntry(ctx, wikiGitRepo, entry) if ctx.Written() { return } @@ -543,27 +544,27 @@ func WikiPages(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.wiki.pages") ctx.Data["CanWriteWiki"] = ctx.Repo.Permission.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived - _, commit, err := findWikiRepoCommit(ctx) + wikiGitRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { ctx.Redirect(ctx.Repo.RepoLink + "/wiki") return } treePath := "" // To support list sub folders' pages in the future - tree, err := commit.SubTree(treePath) + tree, err := commit.SubTree(ctx, wikiGitRepo, treePath) if err != nil { ctx.ServerError("SubTree", err) return } - allEntries, err := tree.ListEntries() + allEntries, err := tree.ListEntries(ctx, wikiGitRepo) if err != nil { ctx.ServerError("ListEntries", err) return } allEntries.CustomSort(base.NaturalSortCompare) - entries, _, err := allEntries.GetCommitsInfo(ctx, ctx.Repo.RepoLink, commit, treePath) + entries, _, err := allEntries.GetCommitsInfo(ctx, ctx.Repo.RepoLink, wikiGitRepo, commit, treePath) if err != nil { ctx.ServerError("GetCommitsInfo", err) return @@ -597,7 +598,7 @@ func WikiPages(ctx *context.Context) { // WikiRaw outputs raw blob requested by user (image for example) func WikiRaw(ctx *context.Context) { - _, commit, err := findWikiRepoCommit(ctx) + wikiGitRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { if git.IsErrNotExist(err) { ctx.NotFound(nil) @@ -612,7 +613,7 @@ func WikiRaw(ctx *context.Context) { var entry *git.TreeEntry if commit != nil { // Try to find a file with that name - entry, err = findEntryForFile(commit, providedGitPath) + entry, err = findEntryForFile(ctx, wikiGitRepo, commit, providedGitPath) if err != nil && !git.IsErrNotExist(err) { ctx.ServerError("findFile", err) return @@ -621,7 +622,7 @@ func WikiRaw(ctx *context.Context) { if entry == nil { // Try to find a wiki page with that name providedGitPath = strings.TrimSuffix(providedGitPath, ".md") - entry, err = findEntryForFile(commit, providedGitPath) + entry, err = findEntryForFile(ctx, wikiGitRepo, commit, providedGitPath) if err != nil && !git.IsErrNotExist(err) { ctx.ServerError("findFile", err) return @@ -630,7 +631,7 @@ func WikiRaw(ctx *context.Context) { } if entry != nil { - if err = common.ServeBlob(ctx.Base, ctx.Repo.Repository, ctx.Repo.TreePath, entry.Blob(), nil); err != nil { + if err = common.ServeBlob(ctx.Base, ctx.Repo.Repository, ctx.Repo.TreePath, entry.Blob(wikiGitRepo), nil); err != nil { ctx.ServerError("ServeBlob", err) } return diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index 28702361e51..be1044d8abc 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -28,28 +28,30 @@ const ( message = "Wiki commit message for unit tests" ) -func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry { +func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) (*git.Repository, *git.TreeEntry) { wikiRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo()) assert.NoError(t, err) - defer wikiRepo.Close() + t.Cleanup(func() { + defer wikiRepo.Close() + }) commit, err := wikiRepo.GetBranchCommit("master") assert.NoError(t, err) - entries, err := commit.ListEntries() + entries, err := commit.Tree().ListEntries(t.Context(), wikiRepo) assert.NoError(t, err) for _, entry := range entries { if entry.Name() == wiki_service.WebPathToGitPath(wikiName) { - return entry + return wikiRepo, entry } } - return nil + return wikiRepo, nil } func wikiContent(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) string { - entry := wikiEntry(t, repo, wikiName) + wikiRepo, entry := wikiEntry(t, repo, wikiName) if !assert.NotNil(t, entry) { return "" } - reader, err := entry.Blob().DataAsync() + reader, err := entry.Blob(wikiRepo).DataAsync() assert.NoError(t, err) defer reader.Close() bytes, err := io.ReadAll(reader) @@ -58,11 +60,13 @@ func wikiContent(t *testing.T, repo *repo_model.Repository, wikiName wiki_servic } func assertWikiExists(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) { - assert.NotNil(t, wikiEntry(t, repo, wikiName)) + _, entry := wikiEntry(t, repo, wikiName) + assert.NotNil(t, entry) } func assertWikiNotExists(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) { - assert.Nil(t, wikiEntry(t, repo, wikiName)) + _, entry := wikiEntry(t, repo, wikiName) + assert.Nil(t, entry) } func assertPagesMetas(t *testing.T, expectedNames []string, metas any) { diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index e4fd4643756..df8980a0e96 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -122,7 +122,7 @@ func FindOwnerProfileReadme(ctx *context.Context, doer *user_model.User, optProf return nil, nil } - profileReadmeBlob, _ = commit.GetBlobByPath("README.md") // no need to handle this error + profileReadmeBlob, _ = commit.GetBlobByPath(ctx, profileGitRepo, "README.md") // no need to handle this error return profileDbRepo, profileReadmeBlob } diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 9e558e2d2f9..f0390a5d0a5 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -185,7 +185,7 @@ func notify(ctx context.Context, input *notifyInput) error { var detectedWorkflows []*actions_module.DetectedWorkflow var filteredWorkflows []*actions_module.DetectedWorkflow actionsConfig := input.Repo.MustGetUnit(ctx, unit_model.TypeActions).ActionsConfig() - workflows, schedules, filtered, err := actions_module.DetectWorkflows(gitRepo, commit, + workflows, schedules, filtered, err := actions_module.DetectWorkflows(ctx, gitRepo, commit, input.Event, input.Payload, shouldDetectSchedules, @@ -231,7 +231,7 @@ func notify(ctx context.Context, input *notifyInput) error { if err != nil { return fmt.Errorf("gitRepo.GetCommit: %w", err) } - baseWorkflows, _, baseFiltered, err := actions_module.DetectWorkflows(gitRepo, baseCommit, input.Event, input.Payload, false) + baseWorkflows, _, baseFiltered, err := actions_module.DetectWorkflows(ctx, gitRepo, baseCommit, input.Event, input.Payload, false) if err != nil { return fmt.Errorf("DetectWorkflows: %w", err) } @@ -602,7 +602,7 @@ func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository) if err != nil { return fmt.Errorf("gitRepo.GetCommit: %w", err) } - scheduleWorkflows, err := actions_module.DetectScheduledWorkflows(gitRepo, commit) + scheduleWorkflows, err := actions_module.DetectScheduledWorkflows(ctx, gitRepo, commit) if err != nil { return fmt.Errorf("detect schedule workflows: %w", err) } @@ -743,6 +743,7 @@ func detectScopedWorkflowsForSource( sourceRepo *repo_model.Repository, ) (sourceCommitSHA string, detected, filtered []*actions_module.DetectedWorkflow, err error) { // scoped workflow content is always taken from the source repo's default branch; the parse is cached per (source, default-branch SHA) and reused across consuming repos/events + sourceCommitSHA, parsed, err := LoadParsedScopedWorkflows(ctx, sourceRepo) if err != nil { return "", nil, nil, err diff --git a/services/actions/reusable_workflow.go b/services/actions/reusable_workflow.go index 2e220cd5ea6..92948394ffd 100644 --- a/services/actions/reusable_workflow.go +++ b/services/actions/reusable_workflow.go @@ -89,7 +89,7 @@ func readWorkflowFromRepo(ctx context.Context, repo *repo_model.Repository, refO if err != nil { return nil, "", fmt.Errorf("get commit %q in %s: %w", refOrSHA, repo.FullName(), err) } - str, err := commit.GetFileContent(path, 1024*1024) + str, err := commit.GetFileContent(ctx, gitRepo, path, 1024*1024) if err != nil { return nil, "", fmt.Errorf("read %s@%s:%s: %w", repo.FullName(), refOrSHA, path, err) } diff --git a/services/actions/scoped_workflow_cache.go b/services/actions/scoped_workflow_cache.go index 3dcfb44d8a5..5a16139934a 100644 --- a/services/actions/scoped_workflow_cache.go +++ b/services/actions/scoped_workflow_cache.go @@ -60,7 +60,7 @@ func LoadParsedScopedWorkflows(ctx context.Context, sourceRepo *repo_model.Repos if err != nil { return "", nil, fmt.Errorf("get source commit %s: %w", sha, err) } - parsed, err = actions_module.ParseScopedWorkflows(sourceCommit) + parsed, err = actions_module.ParseScopedWorkflows(ctx, sourceGitRepo, sourceCommit) if err != nil { return "", nil, err } diff --git a/services/actions/workflow.go b/services/actions/workflow.go index 5b5628cff1d..6d004782a2c 100644 --- a/services/actions/workflow.go +++ b/services/actions/workflow.go @@ -119,7 +119,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re } // resolve the workflow content and record its source on the run (scoped runs read from the source repo) - content, err := resolveDispatchWorkflowContent(ctx, repo, runTargetCommit, workflowID, scopedWorkflowSourceRepoID, isScoped, run) + content, err := resolveDispatchWorkflowContent(ctx, repo, gitRepo, runTargetCommit, workflowID, scopedWorkflowSourceRepoID, isScoped, run) if err != nil { return 0, err } @@ -172,18 +172,18 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re // resolveDispatchWorkflowContent returns the YAML for a dispatched workflow and records its source on the run. // - Repo-level: from the consumer's runTargetCommit. // - Scoped: from the source repo's default branch. -func resolveDispatchWorkflowContent(ctx reqctx.RequestContext, repo *repo_model.Repository, runTargetCommit *git.Commit, workflowID string, sourceRepoID int64, isScoped bool, run *actions_model.ActionRun) ([]byte, error) { +func resolveDispatchWorkflowContent(ctx reqctx.RequestContext, repo *repo_model.Repository, gitRepo *git.Repository, runTargetCommit *git.Commit, workflowID string, sourceRepoID int64, isScoped bool, run *actions_model.ActionRun) ([]byte, error) { if isScoped { return resolveScopedDispatchContent(ctx, repo, sourceRepoID, workflowID, run) } - _, entries, err := actions.ListWorkflows(runTargetCommit) + _, entries, err := actions.ListWorkflows(ctx, gitRepo, runTargetCommit) if err != nil { return nil, err } for _, e := range entries { if e.Name() == workflowID { - return actions.GetContentFromEntry(e) + return actions.GetContentFromEntry(gitRepo, e) } } return nil, util.ErrorWrapTranslatable( diff --git a/services/asymkey/commit_test.go b/services/asymkey/commit_test.go index e0ab47573b9..03eac38aa76 100644 --- a/services/asymkey/commit_test.go +++ b/services/asymkey/commit_test.go @@ -37,7 +37,7 @@ func TestParseCommitWithSSHSignature(t *testing.T) { require.NoError(t, err) t.Run("UserSSHKey", func(t *testing.T) { - commit, err := git.CommitFromReader(nil, git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree a3b1fad553e0f9a2b4a58327bebde36c7da75aa2 + commit, err := git.CommitFromReader(git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree a3b1fad553e0f9a2b4a58327bebde36c7da75aa2 author user2 1752194028 -0700 committer user2 1752194028 -0700 gpgsig -----BEGIN SSH SIGNATURE----- @@ -68,7 +68,7 @@ init project defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")() defer test.MockVariableValue(&setting.Repository.Signing.TrustedSSHKeys, []string{"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH6Y4idVaW3E+bLw1uqoAfJD7o5Siu+HqS51E9oQLPE9"})() - commit, err := git.CommitFromReader(nil, git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree 9a93ffa76e8b72bdb6431910b3a506fa2b39f42e + commit, err := git.CommitFromReader(git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree 9a93ffa76e8b72bdb6431910b3a506fa2b39f42e author User Two 1749230009 +0200 committer User Two 1749230009 +0200 gpgsig -----BEGIN SSH SIGNATURE----- diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 8ff62f60c87..820e633201a 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -365,7 +365,7 @@ func AllHeadCommitsVerified(ctx context.Context, pr *issues_model.PullRequest, g if err != nil { return false, err } - commitList, err := headCommit.CommitsBeforeUntil(git.RefNameFromCommit(mergeBaseCommit)) + commitList, err := headCommit.CommitsBeforeUntil(gitRepo, git.RefNameFromCommit(mergeBaseCommit)) if err != nil { return false, err } diff --git a/services/context/repo.go b/services/context/repo.go index 81df87a67f4..87717f730b6 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -291,7 +291,7 @@ func (r *Repository) RefTypeNameSubURL() string { // GetEditorconfig returns the .editorconfig definition if found in the // HEAD of the default repo branch. -func (r *Repository) GetEditorconfig(optCommit ...*git.Commit) (cfg *editorconfig.Editorconfig, warning, err error) { +func (r *Repository) GetEditorconfig(ctx context.Context, optCommit ...*git.Commit) (cfg *editorconfig.Editorconfig, warning, err error) { if r.GitRepo == nil { return nil, nil, nil } @@ -306,14 +306,14 @@ func (r *Repository) GetEditorconfig(optCommit ...*git.Commit) (cfg *editorconfi return nil, nil, err } } - treeEntry, err := commit.GetTreeEntryByPath(".editorconfig") + treeEntry, err := commit.GetTreeEntryByPath(ctx, r.GitRepo, ".editorconfig") if err != nil { return nil, nil, err } - if treeEntry.Blob().Size() >= setting.UI.MaxDisplayFileSize { + if treeEntry.Blob(r.GitRepo).Size() >= setting.UI.MaxDisplayFileSize { return nil, nil, git.ErrNotExist{ID: "", RelPath: ".editorconfig"} } - reader, err := treeEntry.Blob().DataAsync() + reader, err := treeEntry.Blob(r.GitRepo).DataAsync() if err != nil { return nil, nil, err } diff --git a/services/convert/convert.go b/services/convert/convert.go index 745cdd98978..140af9ffa34 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -523,7 +523,7 @@ func ToActionWorkflowJob(ctx context.Context, repo *repo_model.Repository, task }, nil } -func getActionWorkflowEntry(ctx context.Context, repo *repo_model.Repository, commit *git.Commit, refName git.RefName, folder string, entry *git.TreeEntry) *api.ActionWorkflow { +func getActionWorkflowEntry(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, commit *git.Commit, refName git.RefName, folder string, entry *git.TreeEntry) *api.ActionWorkflow { cfgUnit := repo.MustGetUnit(ctx, unit.TypeActions) cfg := cfgUnit.ActionsConfig() @@ -554,7 +554,7 @@ func getActionWorkflowEntry(ctx context.Context, repo *repo_model.Repository, co createdAt := commit.Author.When updatedAt := commit.Author.When - content, err := actions.GetContentFromEntry(entry) + content, err := actions.GetContentFromEntry(gitRepo, entry) name := entry.Name() if err == nil { workflow, err := model.ReadWorkflow(bytes.NewReader(content)) @@ -589,26 +589,26 @@ func ListActionWorkflows(ctx context.Context, gitrepo *git.Repository, repo *rep return nil, err } - folder, entries, err := actions.ListWorkflows(defaultBranchCommit) + folder, entries, err := actions.ListWorkflows(ctx, gitrepo, defaultBranchCommit) if err != nil { return nil, err } workflows := make([]*api.ActionWorkflow, len(entries)) for i, entry := range entries { - workflows[i] = getActionWorkflowEntry(ctx, repo, defaultBranchCommit, git.RefNameFromBranch(repo.DefaultBranch), folder, entry) + workflows[i] = getActionWorkflowEntry(ctx, repo, gitrepo, defaultBranchCommit, git.RefNameFromBranch(repo.DefaultBranch), folder, entry) } return workflows, nil } -func GetActionWorkflow(ctx context.Context, gitrepo *git.Repository, repo *repo_model.Repository, workflowID string) (*api.ActionWorkflow, error) { - defaultBranchCommit, err := gitrepo.GetBranchCommit(repo.DefaultBranch) +func GetActionWorkflow(ctx context.Context, gitRepo *git.Repository, repo *repo_model.Repository, workflowID string) (*api.ActionWorkflow, error) { + defaultBranchCommit, err := gitRepo.GetBranchCommit(repo.DefaultBranch) if err != nil { return nil, err } - return getActionWorkflowFromCommit(ctx, repo, defaultBranchCommit, git.RefNameFromBranch(repo.DefaultBranch), workflowID) + return getActionWorkflowFromCommit(ctx, repo, gitRepo, defaultBranchCommit, git.RefNameFromBranch(repo.DefaultBranch), workflowID) } func GetActionWorkflowByRef(ctx context.Context, gitrepo *git.Repository, repo *repo_model.Repository, workflowID string, ref git.RefName) (*api.ActionWorkflow, error) { @@ -625,18 +625,18 @@ func GetActionWorkflowByRef(ctx context.Context, gitrepo *git.Repository, repo * return nil, err } - return getActionWorkflowFromCommit(ctx, repo, refCommit, ref, workflowID) + return getActionWorkflowFromCommit(ctx, repo, gitrepo, refCommit, ref, workflowID) } -func getActionWorkflowFromCommit(ctx context.Context, repo *repo_model.Repository, commit *git.Commit, refName git.RefName, workflowID string) (*api.ActionWorkflow, error) { - folder, entries, err := actions.ListWorkflows(commit) +func getActionWorkflowFromCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, commit *git.Commit, refName git.RefName, workflowID string) (*api.ActionWorkflow, error) { + folder, entries, err := actions.ListWorkflows(ctx, gitRepo, commit) if err != nil { return nil, err } for _, entry := range entries { if entry.Name() == workflowID { - return getActionWorkflowEntry(ctx, repo, commit, refName, folder, entry), nil + return getActionWorkflowEntry(ctx, repo, gitRepo, commit, refName, folder, entry), nil } } @@ -650,7 +650,7 @@ func GetScopedActionWorkflow(ctx context.Context, sourceGitRepo *git.Repository, return nil, err } - folder, entries, err := actions.ListScopedWorkflows(commit) + folder, entries, err := actions.ListScopedWorkflows(ctx, sourceGitRepo, commit) if err != nil { return nil, err } @@ -658,7 +658,7 @@ func GetScopedActionWorkflow(ctx context.Context, sourceGitRepo *git.Repository, for _, entry := range entries { if entry.Name() == workflowID { // An empty ref pins HTMLURL to commit (the run's WorkflowCommitSHA) rather than the moving default branch. - wf := getActionWorkflowEntry(ctx, sourceRepo, commit, git.RefName(""), folder, entry) + wf := getActionWorkflowEntry(ctx, sourceRepo, sourceGitRepo, commit, "", folder, entry) // TODO: a scoped workflow has no repo-level representation on the source: the workflow API scans WORKFLOW_DIRS (not SCOPED_WORKFLOW_DIRS), // and the badge only reflects the source's repo-level runs, so neither link resolves a scoped workflow. // Blank them for now and populate once a scoped-aware workflow/badge endpoint exists. diff --git a/services/gitdiff/git_diff_tree.go b/services/gitdiff/git_diff_tree.go index 7ef9bc6165f..c00969b2fc1 100644 --- a/services/gitdiff/git_diff_tree.go +++ b/services/gitdiff/git_diff_tree.go @@ -100,7 +100,7 @@ func validateGitDiffTreeArguments(gitRepo *git.Repository, useMergeBase bool, ba return false, objectFormat.EmptyTree().String(), headCommitID, nil } - baseCommit, err := headCommit.Parent(0) + baseCommit, err := headCommit.Parent(gitRepo, 0) if err != nil { return false, "", "", fmt.Errorf("baseSha is '', attempted to use parent of commit %s, got error: %v", headCommit.ID.String(), err) } diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 686acb26295..0b02ec2aa42 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -477,17 +477,17 @@ type DiffLimitedContent struct { } // GetTailSectionAndLimitedContent creates a fake DiffLineSection if the last section is not the end of the file -func (diffFile *DiffFile) GetTailSectionAndLimitedContent(leftCommit, rightCommit *git.Commit) (_ *DiffSection, diffLimitedContent DiffLimitedContent) { +func (diffFile *DiffFile) GetTailSectionAndLimitedContent(ctx context.Context, gitRepo *git.Repository, leftCommit, rightCommit *git.Commit) (_ *DiffSection, diffLimitedContent DiffLimitedContent) { var leftLineCount, rightLineCount int diffLimitedContent = DiffLimitedContent{} if diffFile.IsBin || diffFile.IsLFSFile { return nil, diffLimitedContent } if (diffFile.Type == DiffFileDel || diffFile.Type == DiffFileChange) && leftCommit != nil { - leftLineCount, diffLimitedContent.LeftContent = getCommitFileLineCountAndLimitedContent(leftCommit, diffFile.OldName) + leftLineCount, diffLimitedContent.LeftContent = getCommitFileLineCountAndLimitedContent(ctx, gitRepo, leftCommit, diffFile.OldName) } if (diffFile.Type == DiffFileAdd || diffFile.Type == DiffFileChange) && rightCommit != nil { - rightLineCount, diffLimitedContent.RightContent = getCommitFileLineCountAndLimitedContent(rightCommit, diffFile.OldName) + rightLineCount, diffLimitedContent.RightContent = getCommitFileLineCountAndLimitedContent(ctx, gitRepo, rightCommit, diffFile.OldName) } if len(diffFile.Sections) == 0 || diffFile.Type != DiffFileChange { return nil, diffLimitedContent @@ -577,8 +577,8 @@ func (l *limitByteWriter) Write(p []byte) (n int, err error) { return l.buf.Write(p) } -func getCommitFileLineCountAndLimitedContent(commit *git.Commit, filePath string) (lineCount int, limitWriter *limitByteWriter) { - blob, err := commit.GetBlobByPath(filePath) +func getCommitFileLineCountAndLimitedContent(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, filePath string) (lineCount int, limitWriter *limitByteWriter) { + blob, err := commit.GetBlobByPath(ctx, gitRepo, filePath) if err != nil { return 0, nil } @@ -1256,7 +1256,7 @@ func guessBeforeCommitForDiff(gitRepo *git.Repository, beforeCommitID string, af actualBeforeCommitID = commitObjectFormat.EmptyTree() } else { if isBeforeCommitIDEmpty { - actualBeforeCommit, err = afterCommit.Parent(0) + actualBeforeCommit, err = afterCommit.Parent(gitRepo, 0) } else { actualBeforeCommit, err = gitRepo.GetCommit(beforeCommitID) } @@ -1360,7 +1360,7 @@ func GetDiffForRender(ctx context.Context, repoLink string, gitRepo *git.Reposit // Populate Submodule URLs if diffFile.SubmoduleDiffInfo != nil { - diffFile.SubmoduleDiffInfo.PopulateURL(repoLink, diffFile, beforeCommit, afterCommit) + diffFile.SubmoduleDiffInfo.PopulateURL(ctx, repoLink, gitRepo, diffFile, beforeCommit, afterCommit) } if !isVendored.Has() { @@ -1372,7 +1372,7 @@ func GetDiffForRender(ctx context.Context, repoLink string, gitRepo *git.Reposit isGenerated = optional.Some(analyze.IsGenerated(diffFile.Name)) } diffFile.IsGenerated = isGenerated.Value() - tailSection, limitedContent := diffFile.GetTailSectionAndLimitedContent(beforeCommit, afterCommit) + tailSection, limitedContent := diffFile.GetTailSectionAndLimitedContent(ctx, gitRepo, beforeCommit, afterCommit) if tailSection != nil { diffFile.Sections = append(diffFile.Sections, tailSection) } @@ -1542,18 +1542,18 @@ func CommentAsDiff(ctx context.Context, c *issues_model.Comment) (*Diff, error) } // GeneratePatchForUnchangedLine creates a patch showing code context for an unchanged line -func GeneratePatchForUnchangedLine(gitRepo *git.Repository, commitID, treePath string, line int64, contextLines int) (string, error) { +func GeneratePatchForUnchangedLine(ctx context.Context, gitRepo *git.Repository, commitID, treePath string, line int64, contextLines int) (string, error) { commit, err := gitRepo.GetCommit(commitID) if err != nil { return "", fmt.Errorf("GetCommit: %w", err) } - entry, err := commit.GetTreeEntryByPath(treePath) + entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, treePath) if err != nil { return "", fmt.Errorf("GetTreeEntryByPath: %w", err) } - blob := entry.Blob() + blob := entry.Blob(gitRepo) dataRc, err := blob.DataAsync() if err != nil { return "", fmt.Errorf("DataAsync: %w", err) diff --git a/services/gitdiff/submodule.go b/services/gitdiff/submodule.go index 9fffd130609..592eb2fe48e 100644 --- a/services/gitdiff/submodule.go +++ b/services/gitdiff/submodule.go @@ -20,7 +20,7 @@ type SubmoduleDiffInfo struct { PreviousRefID string } -func (si *SubmoduleDiffInfo) PopulateURL(repoLink string, diffFile *DiffFile, leftCommit, rightCommit *git.Commit) { +func (si *SubmoduleDiffInfo) PopulateURL(ctx context.Context, repoLink string, gitRepo *git.Repository, diffFile *DiffFile, leftCommit, rightCommit *git.Commit) { si.SubmoduleName = diffFile.Name submoduleCommit := rightCommit // If the submodule is added or updated, check at the right commit if diffFile.IsDeleted { @@ -31,7 +31,7 @@ func (si *SubmoduleDiffInfo) PopulateURL(repoLink string, diffFile *DiffFile, le } submoduleFullPath := diffFile.GetDiffFileName() - submodule, err := submoduleCommit.GetSubModule(submoduleFullPath) + submodule, err := submoduleCommit.GetSubModule(ctx, gitRepo, submoduleFullPath) if err != nil { log.Error("Unable to PopulateURL for submodule %q: GetSubModule: %v", submoduleFullPath, err) return // ignore the error, do not cause 500 errors for end users diff --git a/services/issue/pull.go b/services/issue/pull.go index 260ac5ceaec..78ad6a98967 100644 --- a/services/issue/pull.go +++ b/services/issue/pull.go @@ -68,7 +68,7 @@ func PullRequestCodeOwnersReview(ctx context.Context, pr *issues_model.PullReque var data string for _, file := range codeOwnerFiles { - if blob, err := commit.GetBlobByPath(file); err == nil { + if blob, err := commit.GetBlobByPath(ctx, repo, file); err == nil { data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize) if err == nil { break diff --git a/services/issue/template.go b/services/issue/template.go index c1a0ff2fdd2..daa43d5d547 100644 --- a/services/issue/template.go +++ b/services/issue/template.go @@ -4,6 +4,7 @@ package issue import ( + "context" "fmt" "net/url" "path" @@ -47,17 +48,17 @@ func GetDefaultTemplateConfig() api.IssueConfig { // GetTemplateConfig loads the given issue config file. // It never returns a nil config. -func GetTemplateConfig(gitRepo *git.Repository, path string, commit *git.Commit) (api.IssueConfig, error) { +func GetTemplateConfig(ctx context.Context, gitRepo *git.Repository, path string, commit *git.Commit) (api.IssueConfig, error) { if gitRepo == nil { return GetDefaultTemplateConfig(), nil } - treeEntry, err := commit.GetTreeEntryByPath(path) + treeEntry, err := commit.GetTreeEntryByPath(ctx, gitRepo, path) if err != nil { return GetDefaultTemplateConfig(), err } - reader, err := treeEntry.Blob().DataAsync() + reader, err := treeEntry.Blob(gitRepo).DataAsync() if err != nil { log.Debug("DataAsync: %v", err) return GetDefaultTemplateConfig(), nil @@ -109,7 +110,7 @@ func IsTemplateConfig(path string) bool { // ParseTemplatesFromDefaultBranch parses the issue templates in the repo's default branch, // returns valid templates and the errors of invalid template files (the errors map is guaranteed to be non-nil). -func ParseTemplatesFromDefaultBranch(repo *repo.Repository, gitRepo *git.Repository) (ret struct { +func ParseTemplatesFromDefaultBranch(ctx context.Context, repo *repo.Repository, gitRepo *git.Repository) (ret struct { IssueTemplates []*api.IssueTemplate TemplateErrors map[string]error }, @@ -125,12 +126,12 @@ func ParseTemplatesFromDefaultBranch(repo *repo.Repository, gitRepo *git.Reposit } for _, dirName := range templateDirCandidates { - tree, err := commit.SubTree(dirName) + tree, err := commit.SubTree(ctx, gitRepo, dirName) if err != nil { log.Debug("get sub tree of %s: %v", dirName, err) continue } - entries, err := tree.ListEntries() + entries, err := tree.ListEntries(ctx, gitRepo) if err != nil { log.Debug("list entries in %s: %v", dirName, err) return ret @@ -140,7 +141,7 @@ func ParseTemplatesFromDefaultBranch(repo *repo.Repository, gitRepo *git.Reposit continue } fullName := path.Join(dirName, entry.Name()) - if it, err := template.UnmarshalFromEntry(entry, dirName); err != nil { + if it, err := template.UnmarshalFromEntry(gitRepo, entry, dirName); err != nil { ret.TemplateErrors[fullName] = err } else { if !strings.HasPrefix(it.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/ @@ -155,7 +156,7 @@ func ParseTemplatesFromDefaultBranch(repo *repo.Repository, gitRepo *git.Reposit // GetTemplateConfigFromDefaultBranch returns the issue config for this repo. // It never returns a nil config. -func GetTemplateConfigFromDefaultBranch(repo *repo.Repository, gitRepo *git.Repository) (api.IssueConfig, error) { +func GetTemplateConfigFromDefaultBranch(ctx context.Context, repo *repo.Repository, gitRepo *git.Repository) (api.IssueConfig, error) { if repo.IsEmpty { return GetDefaultTemplateConfig(), nil } @@ -166,24 +167,24 @@ func GetTemplateConfigFromDefaultBranch(repo *repo.Repository, gitRepo *git.Repo } for _, configName := range templateConfigCandidates { - if _, err := commit.GetTreeEntryByPath(configName + ".yaml"); err == nil { - return GetTemplateConfig(gitRepo, configName+".yaml", commit) + if _, err := commit.GetTreeEntryByPath(ctx, gitRepo, configName+".yaml"); err == nil { + return GetTemplateConfig(ctx, gitRepo, configName+".yaml", commit) } - if _, err := commit.GetTreeEntryByPath(configName + ".yml"); err == nil { - return GetTemplateConfig(gitRepo, configName+".yml", commit) + if _, err := commit.GetTreeEntryByPath(ctx, gitRepo, configName+".yml"); err == nil { + return GetTemplateConfig(ctx, gitRepo, configName+".yml", commit) } } return GetDefaultTemplateConfig(), nil } -func HasTemplatesOrContactLinks(repo *repo.Repository, gitRepo *git.Repository) bool { - ret := ParseTemplatesFromDefaultBranch(repo, gitRepo) +func HasTemplatesOrContactLinks(ctx context.Context, repo *repo.Repository, gitRepo *git.Repository) bool { + ret := ParseTemplatesFromDefaultBranch(ctx, repo, gitRepo) if len(ret.IssueTemplates) > 0 { return true } - issueConfig, _ := GetTemplateConfigFromDefaultBranch(repo, gitRepo) + issueConfig, _ := GetTemplateConfigFromDefaultBranch(ctx, repo, gitRepo) return len(issueConfig.ContactLinks) > 0 } diff --git a/services/markup/renderhelper_codepreview.go b/services/markup/renderhelper_codepreview.go index 962cced1a2e..b694816ae8a 100644 --- a/services/markup/renderhelper_codepreview.go +++ b/services/markup/renderhelper_codepreview.go @@ -62,7 +62,7 @@ func renderRepoFileCodePreview(ctx context.Context, opts markup.RenderCodePrevie } language, _ := languagestats.GetFileLanguage(ctx, gitRepo, opts.CommitID, opts.FilePath) - blob, err := commit.GetBlobByPath(opts.FilePath) + blob, err := commit.GetBlobByPath(ctx, gitRepo, opts.FilePath) if err != nil { return "", err } diff --git a/services/pull/merge.go b/services/pull/merge.go index fe65c4d4480..a9e4c36784d 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -72,7 +72,7 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue if err != nil { return "", "", err } - templateContent, err := commit.GetFileContent(templateFilepath, setting.Repository.PullRequest.DefaultMergeMessageSize) + templateContent, err := commit.GetFileContent(ctx, baseGitRepo, templateFilepath, setting.Repository.PullRequest.DefaultMergeMessageSize) if err != nil { if !git.IsErrNotExist(err) { return "", "", err diff --git a/services/pull/pull.go b/services/pull/pull.go index 79a07a9348e..6de1cb86d85 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -1046,7 +1046,7 @@ func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, br return false, err } } - return baseCommit.HasPreviousCommit(headCommit.ID) + return baseCommit.HasPreviousCommit(ctx, baseGitRepo, headCommit.ID) } type CommitInfo struct { diff --git a/services/pull/review.go b/services/pull/review.go index 18abdb04cda..e124b90199d 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -284,7 +284,7 @@ func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_mo // If patch is still empty (unchanged line), generate code context if patch == "" && commitID != "" { - patch, err = gitdiff.GeneratePatchForUnchangedLine(gitRepo, commitID, treePath, line, setting.UI.CodeCommentLines) + patch, err = gitdiff.GeneratePatchForUnchangedLine(ctx, gitRepo, commitID, treePath, line, setting.UI.CodeCommentLines) if err != nil { // Log the error but don't fail comment creation log.Debug("Unable to generate patch for unchanged line (file=%s, line=%d, commit=%s): %v", treePath, line, commitID, err) diff --git a/services/repository/branch.go b/services/repository/branch.go index 0869750db43..4e561ff5b95 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -526,7 +526,7 @@ func UpdateBranch(ctx context.Context, repo *repo_model.Repository, gitRepo *git return nil } - isForcePush, err := newCommit.IsForcePush(branch.CommitID) + isForcePush, err := newCommit.IsForcePush(ctx, gitRepo, branch.CommitID) if err != nil { return err } @@ -811,7 +811,7 @@ func GetBranchDivergingInfo(ctx reqctx.RequestContext, baseRepo *repo_model.Repo if err != nil { return nil, err } - hasPreviousCommit, _ := headCommit.HasPreviousCommit(baseCommitID) + hasPreviousCommit, _ := headCommit.HasPreviousCommit(ctx, headGitRepo, baseCommitID) info.BaseHasNewCommits = !hasPreviousCommit return info, nil } diff --git a/services/repository/cache.go b/services/repository/cache.go index ff1955f1827..6b2e22cb833 100644 --- a/services/repository/cache.go +++ b/services/repository/cache.go @@ -29,5 +29,5 @@ func CacheRef(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep gitRepo.LastCommitCache = git.NewLastCommitCache(commitsCount, repo.FullName(), gitRepo, cache.GetCache()) } - return commit.CacheCommit(ctx) + return commit.CacheCommit(ctx, gitRepo) } diff --git a/services/repository/files/cherry_pick.go b/services/repository/files/cherry_pick.go index 479c76b965d..233fcff694c 100644 --- a/services/repository/files/cherry_pick.go +++ b/services/repository/files/cherry_pick.go @@ -147,7 +147,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod return nil, err } - fileCommitResponse, _ := GetFileCommitResponse(repo, commit) // ok if fails, then will be nil + fileCommitResponse, _ := GetFileCommitResponse(repo, gitRepo, commit) // ok if fails, then will be nil verification := GetPayloadCommitVerification(ctx, commit) fileResponse := &structs.FileResponse{ Commit: fileCommitResponse, diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 42e8c193aa9..5dd43fa9515 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -43,7 +43,7 @@ type GetContentsOrListOptions struct { // GetContentsOrList gets the metadata of a file's contents (*ContentsResponse) if treePath not a tree // directory, otherwise a listing of file contents ([]*ContentsResponse). Ref can be a branch, commit or tag func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, refCommit *utils.RefCommit, opts GetContentsOrListOptions) (ret api.ContentsExtResponse, _ error) { - entry, err := prepareGetContentsEntry(refCommit, &opts.TreePath) + entry, err := prepareGetContentsEntry(ctx, gitRepo, refCommit, &opts.TreePath) if repo.IsEmpty && opts.TreePath == "" { return api.ContentsExtResponse{DirContents: make([]*api.ContentsResponse, 0)}, nil } @@ -58,11 +58,11 @@ func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, gitRepo } // list directory contents - gitTree, err := refCommit.Commit.SubTree(opts.TreePath) + gitTree, err := refCommit.Commit.SubTree(ctx, gitRepo, opts.TreePath) if err != nil { return ret, err } - entries, err := gitTree.ListEntries() + entries, err := gitTree.ListEntries(ctx, gitRepo) if err != nil { return ret, err } @@ -96,7 +96,7 @@ func GetObjectTypeFromTreeEntry(entry *git.TreeEntry) ContentType { } } -func prepareGetContentsEntry(refCommit *utils.RefCommit, treePath *string) (*git.TreeEntry, error) { +func prepareGetContentsEntry(ctx context.Context, gitRepo *git.Repository, refCommit *utils.RefCommit, treePath *string) (*git.TreeEntry, error) { // Check that the path given in opts.treePath is valid (not a git path) cleanTreePath := CleanGitTreePath(*treePath) if cleanTreePath == "" && *treePath != "" { @@ -110,12 +110,12 @@ func prepareGetContentsEntry(refCommit *utils.RefCommit, treePath *string) (*git return nil, util.NewNotExistErrorf("no commit found for the ref [ref: %s]", refCommit.RefName) } - return refCommit.Commit.GetTreeEntryByPath(*treePath) + return refCommit.Commit.GetTreeEntryByPath(ctx, gitRepo, *treePath) } // GetFileContents gets the metadata on a file's contents. Ref can be a branch, commit or tag func GetFileContents(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, refCommit *utils.RefCommit, opts GetContentsOrListOptions) (*api.ContentsResponse, error) { - entry, err := prepareGetContentsEntry(refCommit, &opts.TreePath) + entry, err := prepareGetContentsEntry(ctx, gitRepo, refCommit, &opts.TreePath) if err != nil { return nil, err } @@ -149,7 +149,7 @@ func getFileContentsByEntryInternal(ctx context.Context, repo *repo_model.Reposi Name: entry.Name(), Path: opts.TreePath, SHA: entry.ID.String(), - Size: entry.Size(), + Size: entry.GetSize(ctx, gitRepo), URL: &selfURLString, Links: &api.FileLinksResponse{ Self: &selfURLString, @@ -162,7 +162,7 @@ func getFileContentsByEntryInternal(ctx context.Context, repo *repo_model.Reposi return nil, err } - lastCommit, err := refCommit.Commit.GetCommitByPath(opts.TreePath) + lastCommit, err := refCommit.Commit.GetCommitByPath(gitRepo, opts.TreePath) if err != nil { return nil, err } @@ -205,14 +205,14 @@ func getFileContentsByEntryInternal(ctx context.Context, repo *repo_model.Reposi } else if entry.IsLink() { contentsResponse.Type = string(ContentTypeLink) // The target of a symlink file is the content of the file - targetFromContent, err := entry.Blob().GetBlobContent(1024) + targetFromContent, err := entry.Blob(gitRepo).GetBlobContent(1024) if err != nil { return nil, err } contentsResponse.Target = &targetFromContent } else if entry.IsSubModule() { contentsResponse.Type = string(ContentTypeSubmodule) - submodule, err := commit.GetSubModule(opts.TreePath) + submodule, err := commit.GetSubModule(ctx, gitRepo, opts.TreePath) if err != nil { return nil, err } diff --git a/services/repository/files/file.go b/services/repository/files/file.go index df88ee4d892..c7ba150130e 100644 --- a/services/repository/files/file.go +++ b/services/repository/files/file.go @@ -45,7 +45,7 @@ func GetContentsListFromTreePaths(ctx context.Context, repo *repo_model.Reposito func GetFilesResponseFromCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, refCommit *utils.RefCommit, treeNames []string) (*api.FilesResponse, error) { files := GetContentsListFromTreePaths(ctx, repo, gitRepo, refCommit, treeNames) - fileCommitResponse, _ := GetFileCommitResponse(repo, refCommit.Commit) // ok if fails, then will be nil + fileCommitResponse, _ := GetFileCommitResponse(repo, gitRepo, refCommit.Commit) // ok if fails, then will be nil verification := GetPayloadCommitVerification(ctx, refCommit.Commit) filesResponse := &api.FilesResponse{ Files: files, @@ -70,7 +70,7 @@ func GetFileResponseFromFilesResponse(filesResponse *api.FilesResponse, index in } // GetFileCommitResponse Constructs a FileCommitResponse from a Commit object -func GetFileCommitResponse(repo *repo_model.Repository, commit *git.Commit) (*api.FileCommitResponse, error) { +func GetFileCommitResponse(repo *repo_model.Repository, gitRepo *git.Repository, commit *git.Commit) (*api.FileCommitResponse, error) { if repo == nil { return nil, errors.New("repo cannot be nil") } @@ -78,10 +78,10 @@ func GetFileCommitResponse(repo *repo_model.Repository, commit *git.Commit) (*ap return nil, errors.New("commit cannot be nil") } commitURL, _ := url.Parse(repo.APIURL() + "/git/commits/" + url.PathEscape(commit.ID.String())) - commitTreeURL, _ := url.Parse(repo.APIURL() + "/git/trees/" + url.PathEscape(commit.Tree.ID.String())) + commitTreeURL, _ := url.Parse(repo.APIURL() + "/git/trees/" + url.PathEscape(commit.TreeID.String())) parents := make([]*api.CommitMeta, commit.ParentCount()) - for i := 0; i <= commit.ParentCount(); i++ { - if parent, err := commit.Parent(i); err == nil && parent != nil { + for i := 0; i < commit.ParentCount(); i++ { + if parent, err := commit.Parent(gitRepo, i); err == nil && parent != nil { parentCommitURL, _ := url.Parse(repo.APIURL() + "/git/commits/" + url.PathEscape(parent.ID.String())) parents[i] = &api.CommitMeta{ SHA: parent.ID.String(), @@ -113,7 +113,7 @@ func GetFileCommitResponse(repo *repo_model.Repository, commit *git.Commit) (*ap Message: commit.MessageUTF8(), Tree: &api.CommitMeta{ URL: commitTreeURL.String(), - SHA: commit.Tree.ID.String(), + SHA: commit.TreeID.String(), }, Parents: parents, } diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 8c797a24ec6..4fd7fbaf05c 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -211,7 +211,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user return nil, err } - fileCommitResponse, _ := GetFileCommitResponse(repo, commit) // ok if fails, then will be nil + fileCommitResponse, _ := GetFileCommitResponse(repo, gitRepo, commit) // ok if fails, then will be nil verification := GetPayloadCommitVerification(ctx, commit) fileResponse := &structs.FileResponse{ Commit: fileCommitResponse, diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go index 7b822db0abd..55a4e054af4 100644 --- a/services/repository/files/tree.go +++ b/services/repository/files/tree.go @@ -22,35 +22,20 @@ import ( "gitea.dev/modules/util" ) -// ErrSHANotFound represents a "SHADoesNotMatch" kind of error. -type ErrSHANotFound struct { - SHA string -} - -func (err ErrSHANotFound) Error() string { - return fmt.Sprintf("sha not found [%s]", err.SHA) -} - -func (err ErrSHANotFound) Unwrap() error { - return util.ErrNotExist -} - -// GetTreeBySHA get the GitTreeResponse of a repository using a sha hash. +// GetTreeBySHA get the GitTreeResponse of a repository using a sha hash (id of a commit or a tree) func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) { gitTree, err := gitRepo.GetTree(sha) - if err != nil || gitTree == nil { - return nil, ErrSHANotFound{ // TODO: this error has never been catch outside of this function - SHA: sha, - } + if err != nil { + return nil, util.NewInvalidArgumentErrorf("sha not found [%s]", sha) } tree := new(api.GitTreeResponse) - tree.SHA = gitTree.ResolvedID.String() - tree.URL = repo.APIURL() + "/git/trees/" + url.PathEscape(tree.SHA) + tree.SHA = gitTree.ID.String() // always return the real tree id to end users, but not the commit's id if sha is a commit + tree.URL = repo.APIURL(ctx) + "/git/trees/" + url.PathEscape(tree.SHA) var entries git.Entries if recursive { - entries, err = gitTree.ListEntriesRecursiveWithSize() + entries, err = gitTree.ListEntriesRecursiveWithSize(ctx, gitRepo) } else { - entries, err = gitTree.ListEntries() + entries, err = gitTree.ListEntries(ctx, gitRepo) } if err != nil { return nil, err @@ -79,7 +64,7 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git tree.Entries[i].Path = entries[e].Name() tree.Entries[i].Mode = fmt.Sprintf("%06o", entries[e].Mode()) tree.Entries[i].Type = entries[e].Type() - tree.Entries[i].Size = entries[e].Size() + tree.Entries[i].Size = entries[e].GetSize(ctx, gitRepo) tree.Entries[i].SHA = entries[e].ID.String() if entries[e].IsDir() { @@ -129,14 +114,14 @@ func (node *TreeViewNode) sortLevel() int { return util.Iif(node.EntryMode == "tree" || node.EntryMode == "commit", 0, 1) } -func newTreeViewNodeFromEntry(ctx context.Context, repoLink string, renderedIconPool *fileicon.RenderedIconPool, commit *git.Commit, parentDir string, entry *git.TreeEntry) *TreeViewNode { +func newTreeViewNodeFromEntry(ctx context.Context, repoLink string, renderedIconPool *fileicon.RenderedIconPool, gitRepo *git.Repository, commit *git.Commit, parentDir string, entry *git.TreeEntry) *TreeViewNode { node := &TreeViewNode{ EntryName: entry.Name(), EntryMode: entryModeString(entry.Mode()), FullPath: path.Join(parentDir, entry.Name()), } - entryInfo := fileicon.EntryInfoFromGitTreeEntry(commit, node.FullPath, entry) + entryInfo := fileicon.EntryInfoFromGitTreeEntry(ctx, gitRepo, commit, node.FullPath, entry) node.EntryIcon = fileicon.RenderEntryIconHTML(renderedIconPool, entryInfo) if entryInfo.EntryMode.IsDir() { entryInfo.IsOpen = true @@ -144,7 +129,7 @@ func newTreeViewNodeFromEntry(ctx context.Context, repoLink string, renderedIcon } if node.EntryMode == "commit" { - if subModule, err := commit.GetSubModule(node.FullPath); err != nil { + if subModule, err := commit.GetSubModule(ctx, gitRepo, node.FullPath); err != nil { log.Error("GetSubModule: %v", err) } else if subModule != nil { submoduleFile := git.NewCommitSubmoduleFile(repoLink, node.FullPath, subModule.URL, entry.ID.String()) @@ -169,8 +154,8 @@ func sortTreeViewNodes(nodes []*TreeViewNode) { }) } -func listTreeNodes(ctx context.Context, repoLink string, renderedIconPool *fileicon.RenderedIconPool, commit *git.Commit, tree *git.Tree, treePath, subPath string) ([]*TreeViewNode, error) { - entries, err := tree.ListEntries() +func listTreeNodes(ctx context.Context, repoLink string, renderedIconPool *fileicon.RenderedIconPool, gitRepo *git.Repository, commit *git.Commit, tree *git.Tree, treePath, subPath string) ([]*TreeViewNode, error) { + entries, err := tree.ListEntries(ctx, gitRepo) if err != nil { return nil, err } @@ -178,14 +163,14 @@ func listTreeNodes(ctx context.Context, repoLink string, renderedIconPool *filei subPathDirName, subPathRemaining, _ := strings.Cut(subPath, "/") nodes := make([]*TreeViewNode, 0, len(entries)) for _, entry := range entries { - node := newTreeViewNodeFromEntry(ctx, repoLink, renderedIconPool, commit, treePath, entry) + node := newTreeViewNodeFromEntry(ctx, repoLink, renderedIconPool, gitRepo, commit, treePath, entry) nodes = append(nodes, node) if entry.IsDir() && subPathDirName == entry.Name() { subTreePath := treePath + "/" + node.EntryName if subTreePath[0] == '/' { subTreePath = subTreePath[1:] } - subNodes, err := listTreeNodes(ctx, repoLink, renderedIconPool, commit, entry.Tree(), subTreePath, subPathRemaining) + subNodes, err := listTreeNodes(ctx, repoLink, renderedIconPool, gitRepo, commit, entry.Tree(gitRepo), subTreePath, subPathRemaining) if err != nil { log.Error("listTreeNodes: %v", err) } else { @@ -197,10 +182,10 @@ func listTreeNodes(ctx context.Context, repoLink string, renderedIconPool *filei return nodes, nil } -func GetTreeViewNodes(ctx context.Context, repoLink string, renderedIconPool *fileicon.RenderedIconPool, commit *git.Commit, treePath, subPath string) ([]*TreeViewNode, error) { - entry, err := commit.GetTreeEntryByPath(treePath) +func GetTreeViewNodes(ctx context.Context, repoLink string, renderedIconPool *fileicon.RenderedIconPool, gitRepo *git.Repository, commit *git.Commit, treePath, subPath string) ([]*TreeViewNode, error) { + entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, treePath) if err != nil { return nil, err } - return listTreeNodes(ctx, repoLink, renderedIconPool, commit, entry.Tree(), treePath, subPath) + return listTreeNodes(ctx, repoLink, renderedIconPool, gitRepo, commit, entry.Tree(gitRepo), treePath, subPath) } diff --git a/services/repository/files/tree_test.go b/services/repository/files/tree_test.go index fe42bdb0541..ea67e1248f5 100644 --- a/services/repository/files/tree_test.go +++ b/services/repository/files/tree_test.go @@ -25,17 +25,15 @@ func TestGetTreeBySHA(t *testing.T) { contexttest.LoadGitRepo(t, ctx) defer ctx.Repo.GitRepo.Close() - sha := ctx.Repo.Repository.DefaultBranch page := 1 perPage := 10 - ctx.SetPathParam("id", "1") - ctx.SetPathParam("sha", sha) + ctx.SetPathParam("sha", ctx.Repo.Repository.DefaultBranch) tree, err := GetTreeBySHA(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.PathParam("sha"), page, perPage, true) assert.NoError(t, err) expectedTree := &api.GitTreeResponse{ - SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d", - URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/trees/65f1bf27bc3bf70f64657658635e66094edbcb4d", + SHA: "2a2f1d4670728a2e10049e345bd7a276468beab6", + URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/trees/2a2f1d4670728a2e10049e345bd7a276468beab6", Entries: []api.GitEntry{ { Path: "README.md", @@ -78,7 +76,7 @@ func TestGetTreeViewNodes(t *testing.T) { // With basic theme (default for folders), we get octicon icons without IDs return template.HTML(`octicon-file-directory-open-fill(16/)`) } - treeNodes, err := GetTreeViewNodes(ctx, curRepoLink, renderedIconPool, ctx.Repo.Commit, "", "") + treeNodes, err := GetTreeViewNodes(ctx, curRepoLink, renderedIconPool, ctx.Repo.GitRepo, ctx.Repo.Commit, "", "") assert.NoError(t, err) assert.Equal(t, []*TreeViewNode{ { @@ -90,7 +88,7 @@ func TestGetTreeViewNodes(t *testing.T) { }, }, treeNodes) - treeNodes, err = GetTreeViewNodes(ctx, curRepoLink, renderedIconPool, ctx.Repo.Commit, "", "docs/README.md") + treeNodes, err = GetTreeViewNodes(ctx, curRepoLink, renderedIconPool, ctx.Repo.GitRepo, ctx.Repo.Commit, "", "docs/README.md") assert.NoError(t, err) assert.Equal(t, []*TreeViewNode{ { @@ -110,7 +108,7 @@ func TestGetTreeViewNodes(t *testing.T) { }, }, treeNodes) - treeNodes, err = GetTreeViewNodes(ctx, curRepoLink, renderedIconPool, ctx.Repo.Commit, "docs", "README.md") + treeNodes, err = GetTreeViewNodes(ctx, curRepoLink, renderedIconPool, ctx.Repo.GitRepo, ctx.Repo.Commit, "docs", "README.md") assert.NoError(t, err) assert.Equal(t, []*TreeViewNode{ { diff --git a/services/repository/files/update.go b/services/repository/files/update.go index 8da9021a407..e4a6c7605fe 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -219,7 +219,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } for _, file := range opts.Files { - if err = handleCheckErrors(file, commit, opts); err != nil { + if err = handleCheckErrors(ctx, file, t.gitRepo, commit, opts); err != nil { return nil, err } } @@ -361,12 +361,12 @@ func (err ErrSHAOrCommitIDNotProvided) Error() string { } // handles the check for various issues for ChangeRepoFiles -func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions) error { +func handleCheckErrors(ctx context.Context, file *ChangeRepoFile, gitRepo *git.Repository, commit *git.Commit, opts *ChangeRepoFilesOptions) error { // check old entry (fromTreePath/fromEntry) if file.Operation == "update" || file.Operation == "upload" || file.Operation == "delete" || file.Operation == "rename" { var fromEntryIDString string { - fromEntry, err := commit.GetTreeEntryByPath(file.Options.fromTreePath) + fromEntry, err := commit.GetTreeEntryByPath(ctx, gitRepo, file.Options.fromTreePath) if file.Operation == "upload" && git.IsErrNotExist(err) { fromEntry = nil } else if err != nil { @@ -391,7 +391,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep // If a lastCommitID given doesn't match the branch head's commitID throw // an error, but only if we aren't creating a new branch. if commit.ID.String() != opts.LastCommitID && opts.OldBranch == opts.NewBranch { - if changed, err := commit.FileChangedSinceCommit(file.Options.treePath, opts.LastCommitID); err != nil { + if changed, err := commit.FileChangedSinceCommit(gitRepo, file.Options.treePath, opts.LastCommitID); err != nil { return err } else if changed { return ErrCommitIDDoesNotMatch{ @@ -417,7 +417,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep subTreePath := "" for index, part := range treePathParts { subTreePath = path.Join(subTreePath, part) - entry, err := commit.GetTreeEntryByPath(subTreePath) + entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, subTreePath) if err != nil { if git.IsErrNotExist(err) { // Means there is no item with that name, so we're good @@ -596,7 +596,7 @@ func writeRepoObjectForRename(ctx context.Context, t *TemporaryUploadRepository, if err != nil { return nil, err } - oldEntry, err := commit.GetTreeEntryByPath(file.Options.fromTreePath) + oldEntry, err := commit.GetTreeEntryByPath(ctx, t.gitRepo, file.Options.fromTreePath) if err != nil { return nil, err } @@ -619,7 +619,7 @@ func writeRepoObjectForRename(ctx context.Context, t *TemporaryUploadRepository, } oldEntryBlobPointerBy := func(f func(r io.Reader) (lfs.Pointer, error)) (lfsPointer lfs.Pointer, err error) { - r, err := oldEntry.Blob().DataAsync() + r, err := oldEntry.Blob(t.gitRepo).DataAsync() if err != nil { return lfsPointer, err } @@ -645,7 +645,7 @@ func writeRepoObjectForRename(ctx context.Context, t *TemporaryUploadRepository, if err != nil { return nil, err } - ret.LfsContent, err = oldEntry.Blob().DataAsync() + ret.LfsContent, err = oldEntry.Blob(t.gitRepo).DataAsync() if err != nil { return nil, err } diff --git a/services/repository/license.go b/services/repository/license.go index 61c58e72820..959565d393e 100644 --- a/services/repository/license.go +++ b/services/repository/license.go @@ -84,7 +84,7 @@ func repoLicenseUpdater(items ...*LicenseUpdaterOptions) []*LicenseUpdaterOption log.Error("repoLicenseUpdater [%d] failed: GetBranchCommit: %v", opts.RepoID, err) continue } - if err = UpdateRepoLicenses(ctx, repo, commit); err != nil { + if err = UpdateRepoLicenses(ctx, repo, gitRepo, commit); err != nil { log.Error("repoLicenseUpdater [%d] failed: updateRepoLicenses: %v", opts.RepoID, err) } } @@ -115,12 +115,12 @@ func SyncRepoLicenses(ctx context.Context) error { } // UpdateRepoLicenses will update repository licenses col if license file exists -func UpdateRepoLicenses(ctx context.Context, repo *repo_model.Repository, commit *git.Commit) error { +func UpdateRepoLicenses(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, commit *git.Commit) error { if commit == nil { return nil } - b, err := commit.GetBlobByPath(LicenseFileName) + b, err := commit.GetBlobByPath(ctx, gitRepo, LicenseFileName) if err != nil && !git.IsErrNotExist(err) { return fmt.Errorf("GetBlobByPath: %w", err) } diff --git a/services/repository/push.go b/services/repository/push.go index 7666ecf377b..678a4bd5e6d 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -168,9 +168,9 @@ func pushQueueHandleUpdates(optsList []*repo_module.PushUpdateOptions) error { // Push new branch. var l []*git.Commit if opts.IsNewRef() { - l, err = pushNewBranch(ctx, repo, pusher, opts, newCommit) + l, err = pushNewBranch(ctx, repo, gitRepo, pusher, opts, newCommit) } else { - l, err = pushUpdateBranch(ctx, repo, pusher, opts, newCommit) + l, err = pushUpdateBranch(ctx, repo, gitRepo, pusher, opts, newCommit) } if err != nil { return err @@ -264,7 +264,7 @@ func getCompareURL(repo *repo_model.Repository, gitRepo *git.Repository, objectF return "" } -func pushNewBranch(ctx context.Context, repo *repo_model.Repository, pusher *user_model.User, opts *repo_module.PushUpdateOptions, newCommit *git.Commit) ([]*git.Commit, error) { +func pushNewBranch(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, pusher *user_model.User, opts *repo_module.PushUpdateOptions, newCommit *git.Commit) ([]*git.Commit, error) { if repo.IsEmpty { // Change default branch and empty status only if pushed ref is non-empty branch. repo.DefaultBranch = opts.RefName() repo.IsEmpty = false @@ -279,7 +279,7 @@ func pushNewBranch(ctx context.Context, repo *repo_model.Repository, pusher *use } } - l, err := newCommit.CommitsBeforeLimit(10) + l, err := newCommit.CommitsBeforeLimit(gitRepo, 10) if err != nil { return nil, fmt.Errorf("newCommit.CommitsBeforeLimit: %w", err) } @@ -287,15 +287,15 @@ func pushNewBranch(ctx context.Context, repo *repo_model.Repository, pusher *use return l, nil } -func pushUpdateBranch(_ context.Context, repo *repo_model.Repository, pusher *user_model.User, opts *repo_module.PushUpdateOptions, newCommit *git.Commit) ([]*git.Commit, error) { - l, err := newCommit.CommitsBeforeUntil(git.RefNameFromCommit(opts.OldCommitID)) +func pushUpdateBranch(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, pusher *user_model.User, opts *repo_module.PushUpdateOptions, newCommit *git.Commit) ([]*git.Commit, error) { + l, err := newCommit.CommitsBeforeUntil(gitRepo, git.RefNameFromCommit(opts.OldCommitID)) if err != nil { return nil, fmt.Errorf("newCommit.CommitsBeforeUntil: %w", err) } branch := opts.RefFullName.BranchName() - isForcePush, err := newCommit.IsForcePush(opts.OldCommitID) + isForcePush, err := newCommit.IsForcePush(ctx, gitRepo, opts.OldCommitID) if err != nil { log.Error("IsForcePush %s:%s failed: %v", repo.FullName(), branch, err) } diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index 9b1160d7d99..11d2717ad65 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -174,7 +174,7 @@ func TestRepository_AddWikiPage(t *testing.T) { masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch) assert.NoError(t, err) gitPath := WebPathToGitPath(webPath) - entry, err := masterTree.GetTreeEntryByPath(gitPath) + entry, err := masterTree.GetTreeEntryByPath(t.Context(), gitRepo, gitPath) assert.NoError(t, err) assert.Equal(t, gitPath, entry.Name(), "%s not added correctly", userTitle) }) @@ -219,12 +219,12 @@ func TestRepository_EditWikiPage(t *testing.T) { masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch) assert.NoError(t, err) gitPath := WebPathToGitPath(webPath) - entry, err := masterTree.GetTreeEntryByPath(gitPath) + entry, err := masterTree.GetTreeEntryByPath(t.Context(), gitRepo, gitPath) assert.NoError(t, err) assert.Equal(t, gitPath, entry.Name(), "%s not edited correctly", newWikiName) if newWikiName != "Home" { - _, err := masterTree.GetTreeEntryByPath("Home.md") + _, err := masterTree.GetTreeEntryByPath(t.Context(), gitRepo, "Home.md") assert.Error(t, err) } gitRepo.Close() @@ -245,7 +245,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch) assert.NoError(t, err) gitPath := WebPathToGitPath("Home") - _, err = masterTree.GetTreeEntryByPath(gitPath) + _, err = masterTree.GetTreeEntryByPath(t.Context(), gitRepo, gitPath) assert.Error(t, err) } diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl index e79eac1dd13..f595b41ac8a 100644 --- a/templates/repo/view_list.tmpl +++ b/templates/repo/view_list.tmpl @@ -34,7 +34,7 @@ {{end}} {{else}} {{if $entry.IsDir}} - {{$subJumpablePathName := $entry.GetSubJumpablePathName}} + {{$subJumpablePathName := call $.GetSubJumpablePathName $entry}} {{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}} {{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}} diff --git a/tests/integration/api_packages_cargo_test.go b/tests/integration/api_packages_cargo_test.go index 37693ecfdc2..265749c37ed 100644 --- a/tests/integration/api_packages_cargo_test.go +++ b/tests/integration/api_packages_cargo_test.go @@ -83,7 +83,7 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) { commit, err := gitRepo.GetBranchCommit(repo.DefaultBranch) assert.NoError(t, err) - blob, err := commit.GetBlobByPath(path) + blob, err := commit.GetBlobByPath(t.Context(), gitRepo, path) assert.NoError(t, err) content, err := blob.GetBlobContent(1024) diff --git a/tests/integration/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go index 52a3a163f19..72ba1563d0c 100644 --- a/tests/integration/api_repo_get_contents_list_test.go +++ b/tests/integration/api_repo_get_contents_list_test.go @@ -120,7 +120,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { assert.NotNil(t, contentsListResponse) branchCommit, err := gitRepo.GetBranchCommit(ref) assert.NoError(t, err) - lastCommit, err = branchCommit.GetCommitByPath("README.md") + lastCommit, err = branchCommit.GetCommitByPath(gitRepo, "README.md") assert.NoError(t, err) expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String()) assert.Equal(t, expectedContentsListResponse, contentsListResponse) @@ -134,7 +134,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { assert.NotNil(t, contentsListResponse) tagCommit, err := gitRepo.GetTagCommit(ref) assert.NoError(t, err) - lastCommit, err = tagCommit.GetCommitByPath("README.md") + lastCommit, err = tagCommit.GetCommitByPath(gitRepo, "README.md") assert.NoError(t, err) expectedContentsListResponse = getExpectedContentsListResponseForContents(ref, refType, lastCommit.ID.String()) assert.Equal(t, expectedContentsListResponse, contentsListResponse) diff --git a/tests/integration/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go index 61d4bba1a41..c12886d5832 100644 --- a/tests/integration/api_repo_get_contents_test.go +++ b/tests/integration/api_repo_get_contents_test.go @@ -125,7 +125,7 @@ func testAPIGetContents(t *testing.T, _ *url.URL) { resp = MakeRequest(t, req, http.StatusOK) contentsResponse = DecodeJSON(t, resp, &api.ContentsResponse{}) branchCommit, _ := gitRepo.GetBranchCommit(ref) - lastCommit, _ = branchCommit.GetCommitByPath("README.md") + lastCommit, _ = branchCommit.GetCommitByPath(gitRepo, "README.md") expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String()) assert.Equal(t, *expectedContentsResponse, *contentsResponse) @@ -136,7 +136,7 @@ func testAPIGetContents(t *testing.T, _ *url.URL) { resp = MakeRequest(t, req, http.StatusOK) contentsResponse = DecodeJSON(t, resp, &api.ContentsResponse{}) tagCommit, _ := gitRepo.GetTagCommit(ref) - lastCommit, _ = tagCommit.GetCommitByPath("README.md") + lastCommit, _ = tagCommit.GetCommitByPath(gitRepo, "README.md") expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String()) assert.Equal(t, *expectedContentsResponse, *contentsResponse) diff --git a/tests/integration/git_misc_test.go b/tests/integration/git_misc_test.go index 4747d2bd095..575fd3d15b6 100644 --- a/tests/integration/git_misc_test.go +++ b/tests/integration/git_misc_test.go @@ -50,10 +50,10 @@ func TestDataAsyncDoubleRead_Issue29101(t *testing.T) { commit, err := gitRepo.GetCommit(sha) assert.NoError(t, err) - entry, err := commit.GetTreeEntryByPath("test.txt") + entry, err := commit.GetTreeEntryByPath(t.Context(), gitRepo, "test.txt") assert.NoError(t, err) - b := entry.Blob() + b := entry.Blob(gitRepo) r1, err := b.DataAsync() assert.NoError(t, err) defer r1.Close() diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go index 05f9b027d3e..7f586e8880a 100644 --- a/tests/integration/repofiles_change_test.go +++ b/tests/integration/repofiles_change_test.go @@ -403,7 +403,7 @@ func TestChangeRepoFilesForUpdate(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + lastCommit, _ := commit.GetCommitByPath(gitRepo, opts.Files[0].TreePath) expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When) assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0]) assert.Equal(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) @@ -439,17 +439,17 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + lastCommit, _ := commit.GetCommitByPath(gitRepo, opts.Files[0].TreePath) expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When) // assert that the old file no longer exists in the last commit of the branch - fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath) + fromEntry, err := commit.GetTreeEntryByPath(ctx, gitRepo, opts.Files[0].FromTreePath) switch err.(type) { case git.ErrNotExist: // correct, continue default: t.Fatalf("expected git.ErrNotExist, got:%v", err) } - toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath) + toEntry, err := commit.GetTreeEntryByPath(ctx, gitRepo, opts.Files[0].TreePath) assert.NoError(t, err) assert.Nil(t, fromEntry) // Should no longer exist here assert.NotNil(t, toEntry) // Should exist here @@ -485,7 +485,7 @@ func TestChangeRepoFilesForUpdateWithFileRename(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + lastCommit, _ := commit.GetCommitByPath(gitRepo, opts.Files[0].TreePath) expectedFileResponse := getExpectedFileResponseForRepoFilesUpdateRename(commit.ID.String(), lastCommit.ID.String()) for _, file := range filesResponse.Files { file.LastCommitterDate, file.LastAuthorDate = nil, nil // there might be different time in one operation, so we ignore them @@ -522,7 +522,7 @@ func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + lastCommit, _ := commit.GetCommitByPath(gitRepo, opts.Files[0].TreePath) expectedFileResponse := getExpectedFileResponseForRepoFilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String(), lastCommit.Committer.When, lastCommit.Author.When) assert.Equal(t, expectedFileResponse.Content, filesResponse.Files[0]) })