From c31ae1a651d3be4da1f45ec2ccb6964aa6282268 Mon Sep 17 00:00:00 2001
From: Earl Warren <contact@earl-warren.org>
Date: Fri, 26 Apr 2024 09:22:09 +0000
Subject: [PATCH] fix(lfs): gogit /settings/lfs/find 500 error (#3472)

Refs: https://codeberg.org/forgejo/forgejo/pulls/3448
Refs: https://codeberg.org/forgejo/forgejo/issues/3438
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3472
Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
---
 modules/git/pipeline/lfs_common.go            | 32 ++++++++++++++++++
 modules/git/pipeline/{lfs.go => lfs_gogit.go} | 25 ++------------
 modules/git/pipeline/lfs_nogogit.go           | 33 ++++---------------
 templates/repo/settings/lfs_file_find.tmpl    |  4 +--
 4 files changed, 44 insertions(+), 50 deletions(-)
 create mode 100644 modules/git/pipeline/lfs_common.go
 rename modules/git/pipeline/{lfs.go => lfs_gogit.go} (80%)

diff --git a/modules/git/pipeline/lfs_common.go b/modules/git/pipeline/lfs_common.go
new file mode 100644
index 0000000000..188e7d4d65
--- /dev/null
+++ b/modules/git/pipeline/lfs_common.go
@@ -0,0 +1,32 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pipeline
+
+import (
+	"fmt"
+	"time"
+
+	"code.gitea.io/gitea/modules/git"
+)
+
+// LFSResult represents commits found using a provided pointer file hash
+type LFSResult struct {
+	Name           string
+	SHA            string
+	Summary        string
+	When           time.Time
+	ParentHashes   []git.ObjectID
+	BranchName     string
+	FullCommitName string
+}
+
+type lfsResultSlice []*LFSResult
+
+func (a lfsResultSlice) Len() int           { return len(a) }
+func (a lfsResultSlice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) }
+
+func lfsError(msg string, err error) error {
+	return fmt.Errorf("LFS error occurred, %s: err: %w", msg, err)
+}
diff --git a/modules/git/pipeline/lfs.go b/modules/git/pipeline/lfs_gogit.go
similarity index 80%
rename from modules/git/pipeline/lfs.go
rename to modules/git/pipeline/lfs_gogit.go
index 6dfca24f29..adcf8ed09c 100644
--- a/modules/git/pipeline/lfs.go
+++ b/modules/git/pipeline/lfs_gogit.go
@@ -7,12 +7,10 @@ package pipeline
 
 import (
 	"bufio"
-	"fmt"
 	"io"
 	"sort"
 	"strings"
 	"sync"
-	"time"
 
 	"code.gitea.io/gitea/modules/git"
 
@@ -21,23 +19,6 @@ import (
 	"github.com/go-git/go-git/v5/plumbing/object"
 )
 
-// LFSResult represents commits found using a provided pointer file hash
-type LFSResult struct {
-	Name           string
-	SHA            string
-	Summary        string
-	When           time.Time
-	ParentHashes   []git.ObjectID
-	BranchName     string
-	FullCommitName string
-}
-
-type lfsResultSlice []*LFSResult
-
-func (a lfsResultSlice) Len() int           { return len(a) }
-func (a lfsResultSlice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) }
-
 // FindLFSFile finds commits that contain a provided pointer file hash
 func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) {
 	resultsMap := map[string]*LFSResult{}
@@ -51,7 +32,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 		All:   true,
 	})
 	if err != nil {
-		return nil, fmt.Errorf("Failed to get GoGit CommitsIter. Error: %w", err)
+		return nil, lfsError("failed to get GoGit CommitsIter", err)
 	}
 
 	err = commitsIter.ForEach(func(gitCommit *object.Commit) error {
@@ -85,7 +66,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 		return nil
 	})
 	if err != nil && err != io.EOF {
-		return nil, fmt.Errorf("Failure in CommitIter.ForEach: %w", err)
+		return nil, lfsError("failure in CommitIter.ForEach", err)
 	}
 
 	for _, result := range resultsMap {
@@ -156,7 +137,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 	select {
 	case err, has := <-errChan:
 		if has {
-			return nil, fmt.Errorf("Unable to obtain name for LFS files. Error: %w", err)
+			return nil, lfsError("unable to obtain name for LFS files", err)
 		}
 	default:
 	}
diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go
index 4c65249089..a3ee883968 100644
--- a/modules/git/pipeline/lfs_nogogit.go
+++ b/modules/git/pipeline/lfs_nogogit.go
@@ -8,33 +8,14 @@ package pipeline
 import (
 	"bufio"
 	"bytes"
-	"fmt"
 	"io"
 	"sort"
 	"strings"
 	"sync"
-	"time"
 
 	"code.gitea.io/gitea/modules/git"
 )
 
-// LFSResult represents commits found using a provided pointer file hash
-type LFSResult struct {
-	Name           string
-	SHA            string
-	Summary        string
-	When           time.Time
-	ParentIDs      []git.ObjectID
-	BranchName     string
-	FullCommitName string
-}
-
-type lfsResultSlice []*LFSResult
-
-func (a lfsResultSlice) Len() int           { return len(a) }
-func (a lfsResultSlice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) }
-
 // FindLFSFile finds commits that contain a provided pointer file hash
 func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) {
 	resultsMap := map[string]*LFSResult{}
@@ -137,11 +118,11 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 					n += int64(count)
 					if bytes.Equal(binObjectID, objectID.RawValue()) {
 						result := LFSResult{
-							Name:      curPath + string(fname),
-							SHA:       curCommit.ID.String(),
-							Summary:   strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0],
-							When:      curCommit.Author.When,
-							ParentIDs: curCommit.Parents,
+							Name:         curPath + string(fname),
+							SHA:          curCommit.ID.String(),
+							Summary:      strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0],
+							When:         curCommit.Author.When,
+							ParentHashes: curCommit.Parents,
 						}
 						resultsMap[curCommit.ID.String()+":"+curPath+string(fname)] = &result
 					} else if string(mode) == git.EntryModeTree.String() {
@@ -183,7 +164,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 
 	for _, result := range resultsMap {
 		hasParent := false
-		for _, parentID := range result.ParentIDs {
+		for _, parentID := range result.ParentHashes {
 			if _, hasParent = resultsMap[parentID.String()+":"+result.Name]; hasParent {
 				break
 			}
@@ -241,7 +222,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 	select {
 	case err, has := <-errChan:
 		if has {
-			return nil, fmt.Errorf("Unable to obtain name for LFS files. Error: %w", err)
+			return nil, lfsError("unable to obtain name for LFS files", err)
 		}
 	default:
 	}
diff --git a/templates/repo/settings/lfs_file_find.tmpl b/templates/repo/settings/lfs_file_find.tmpl
index 54dbdb482b..809a028b2c 100644
--- a/templates/repo/settings/lfs_file_find.tmpl
+++ b/templates/repo/settings/lfs_file_find.tmpl
@@ -23,9 +23,9 @@
 								<span class="text grey">{{svg "octicon-git-branch"}}{{.BranchName}}</span>
 							</td>
 							<td>
-								{{if .ParentIDs}}
+								{{if .ParentHashes}}
 									{{ctx.Locale.Tr "repo.diff.parent"}}
-									{{range .ParentIDs}}
+									{{range .ParentHashes}}
 										<a class="ui primary sha label" href="{{$.RepoLink}}/commit/{{.String}}">{{ShortSha .String}}</a>
 									{{end}}
 								{{end}}