summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2021-02-10 07:00:57 +0000
committerGitHub <noreply@github.com>2021-02-10 07:00:57 +0000
commitf9abf94bd99b5b9c603037aaad4dd327b68263bd (patch)
tree05a1ad16773a0bf778f7ceec6bb1c21c2b3f387b
parentc0c59a4c99538fcc246ec3209a14db41a5f7dc3f (diff)
downloadgitea-f9abf94bd99b5b9c603037aaad4dd327b68263bd.tar.gz
gitea-f9abf94bd99b5b9c603037aaad4dd327b68263bd.zip
HasPreviousCommit causes recursive load of commits unnecessarily (#14598)
This PR improves HasPreviousCommit to prevent the automatic and recursive loading of previous commits using git merge-base --is-ancestor and git rev-list Fix #13684 Signed-off-by: Andrew Thornton <art27@cantab.net>
-rw-r--r--modules/git/commit.go38
-rw-r--r--modules/git/commit_test.go25
2 files changed, 50 insertions, 13 deletions
diff --git a/modules/git/commit.go b/modules/git/commit.go
index ce82c2f582..027642720d 100644
--- a/modules/git/commit.go
+++ b/modules/git/commit.go
@@ -9,6 +9,7 @@ import (
"bufio"
"bytes"
"container/list"
+ "errors"
"fmt"
"image"
"image/color"
@@ -17,6 +18,7 @@ import (
_ "image/png" // for processing png images
"io"
"net/http"
+ "os/exec"
"strconv"
"strings"
)
@@ -264,23 +266,33 @@ func (c *Commit) CommitsBefore() (*list.List, error) {
// HasPreviousCommit returns true if a given commitHash is contained in commit's parents
func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) {
- for i := 0; i < c.ParentCount(); i++ {
- commit, err := c.Parent(i)
- if err != nil {
- return false, err
- }
- if commit.ID == commitHash {
+ this := c.ID.String()
+ that := commitHash.String()
+
+ if this == that {
+ return false, nil
+ }
+
+ if err := CheckGitVersionAtLeast("1.8"); err == nil {
+ _, err := NewCommand("merge-base", "--is-ancestor", that, this).RunInDir(c.repo.Path)
+ if err == nil {
return true, nil
}
- commitInParentCommit, err := commit.HasPreviousCommit(commitHash)
- if err != nil {
- return false, err
- }
- if commitInParentCommit {
- return true, nil
+ var exitError *exec.ExitError
+ if errors.As(err, &exitError) {
+ if exitError.ProcessState.ExitCode() == 1 && len(exitError.Stderr) == 0 {
+ return false, nil
+ }
}
+ return false, err
+ }
+
+ result, err := NewCommand("rev-list", "--ancestry-path", "-n1", that+".."+this, "--").RunInDir(c.repo.Path)
+ if err != nil {
+ return false, err
}
- return false, nil
+
+ return len(strings.TrimSpace(result)) > 0, nil
}
// CommitsBeforeLimit returns num commits before current revision
diff --git a/modules/git/commit_test.go b/modules/git/commit_test.go
index 9b5fc8f660..0925a6ce6a 100644
--- a/modules/git/commit_test.go
+++ b/modules/git/commit_test.go
@@ -105,3 +105,28 @@ empty commit`, commitFromReader.Signature.Payload)
commitFromReader.Signature.Payload += "\n\n"
assert.EqualValues(t, commitFromReader, commitFromReader2)
}
+
+func TestHasPreviousCommit(t *testing.T) {
+ bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
+
+ repo, err := OpenRepository(bareRepo1Path)
+ assert.NoError(t, err)
+
+ commit, err := repo.GetCommit("8006ff9adbf0cb94da7dad9e537e53817f9fa5c0")
+ assert.NoError(t, err)
+
+ parentSHA := MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2")
+ notParentSHA := MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3")
+
+ haz, err := commit.HasPreviousCommit(parentSHA)
+ assert.NoError(t, err)
+ assert.True(t, haz)
+
+ hazNot, err := commit.HasPreviousCommit(notParentSHA)
+ assert.NoError(t, err)
+ assert.False(t, hazNot)
+
+ selfNot, err := commit.HasPreviousCommit(commit.ID)
+ assert.NoError(t, err)
+ assert.False(t, selfNot)
+}