]> source.dussan.org Git - gitea.git/commitdiff
HasPreviousCommit causes recursive load of commits unnecessarily (#14598) (#14649)
authorzeripath <art27@cantab.net>
Sun, 14 Feb 2021 22:44:26 +0000 (22:44 +0000)
committerGitHub <noreply@github.com>
Sun, 14 Feb 2021 22:44:26 +0000 (00:44 +0200)
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>
Co-authored-by: 6543 <6543@obermui.de>
modules/git/commit.go

index 6d2bc2b02cfbb294f17376cb5560f231f20c1459..b7d2c3a9f33cf4eb1dc5df89ae2908d342373066 100644 (file)
@@ -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"
 
@@ -309,23 +311,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 := CheckGitVersionConstraint(">= 1.8.0"); 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