mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 10:56:10 +01:00 
			
		
		
		
	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>
This commit is contained in:
		| @@ -9,6 +9,7 @@ import ( | |||||||
| 	"bufio" | 	"bufio" | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"container/list" | 	"container/list" | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"image" | 	"image" | ||||||
| 	"image/color" | 	"image/color" | ||||||
| @@ -17,6 +18,7 @@ import ( | |||||||
| 	_ "image/png"  // for processing png images | 	_ "image/png"  // for processing png images | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"os/exec" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"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 | // HasPreviousCommit returns true if a given commitHash is contained in commit's parents | ||||||
| func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) { | func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) { | ||||||
| 	for i := 0; i < c.ParentCount(); i++ { | 	this := c.ID.String() | ||||||
| 		commit, err := c.Parent(i) | 	that := commitHash.String() | ||||||
| 		if err != nil { |  | ||||||
| 			return false, err | 	if this == that { | ||||||
| 		} |  | ||||||
| 		if commit.ID == commitHash { |  | ||||||
| 			return true, nil |  | ||||||
| 		} |  | ||||||
| 		commitInParentCommit, err := commit.HasPreviousCommit(commitHash) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return false, err |  | ||||||
| 		} |  | ||||||
| 		if commitInParentCommit { |  | ||||||
| 			return true, nil |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 		return false, nil | 		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 | ||||||
|  | 		} | ||||||
|  | 		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 len(strings.TrimSpace(result)) > 0, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // CommitsBeforeLimit returns num commits before current revision | // CommitsBeforeLimit returns num commits before current revision | ||||||
|   | |||||||
| @@ -105,3 +105,28 @@ empty commit`, commitFromReader.Signature.Payload) | |||||||
| 	commitFromReader.Signature.Payload += "\n\n" | 	commitFromReader.Signature.Payload += "\n\n" | ||||||
| 	assert.EqualValues(t, commitFromReader, commitFromReader2) | 	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) | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user