diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2024-08-06 21:32:49 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-06 13:32:49 +0000 |
commit | df7f1c2eadac24f64adf3d823a7642a6eccf77f3 (patch) | |
tree | 6896c20f779367f5749547e60fdcf302c67095d3 /modules/git | |
parent | de175e3b06e623280058278cdb0a62de7443cd86 (diff) | |
download | gitea-df7f1c2eadac24f64adf3d823a7642a6eccf77f3.tar.gz gitea-df7f1c2eadac24f64adf3d823a7642a6eccf77f3.zip |
Fix protected branch files detection on pre_receive hook (#31778)
Fix #31738
When pushing a new branch, the old commit is zero. Most git commands
cannot recognize the zero commit id. To get the changed files in the
push, we need to get the first diverge commit of this branch. In most
situations, we could check commits one by one until one commit is
contained by another branch. Then we will think that commit is the
diverge point.
And in a pre-receive hook, this will be more difficult because all
commits haven't been merged and they actually stored in a temporary
place by git. So we need to bring some envs to let git know the commit
exist.
Diffstat (limited to 'modules/git')
-rw-r--r-- | modules/git/commit_test.go | 17 | ||||
-rw-r--r-- | modules/git/diff.go | 12 | ||||
-rw-r--r-- | modules/git/repo_commit.go | 49 | ||||
-rw-r--r-- | modules/git/repo_commit_test.go | 3 |
4 files changed, 74 insertions, 7 deletions
diff --git a/modules/git/commit_test.go b/modules/git/commit_test.go index a33e7df31a..0ddeb182ef 100644 --- a/modules/git/commit_test.go +++ b/modules/git/commit_test.go @@ -4,6 +4,8 @@ package git import ( + "context" + "os" "path/filepath" "strings" "testing" @@ -345,3 +347,18 @@ func TestGetCommitFileStatusMerges(t *testing.T) { assert.Equal(t, commitFileStatus.Removed, expected.Removed) assert.Equal(t, commitFileStatus.Modified, expected.Modified) } + +func Test_GetCommitBranchStart(t *testing.T) { + bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") + repo, err := OpenRepository(context.Background(), bareRepo1Path) + assert.NoError(t, err) + defer repo.Close() + commit, err := repo.GetBranchCommit("branch1") + assert.NoError(t, err) + assert.EqualValues(t, "2839944139e0de9737a044f78b0e4b40d989a9e3", commit.ID.String()) + + startCommitID, err := repo.GetCommitBranchStart(os.Environ(), "branch1", commit.ID.String()) + assert.NoError(t, err) + assert.NotEmpty(t, startCommitID) + assert.EqualValues(t, "9c9aef8dd84e02bc7ec12641deb4c930a7c30185", startCommitID) +} diff --git a/modules/git/diff.go b/modules/git/diff.go index 10ef3d83fb..833f6220f9 100644 --- a/modules/git/diff.go +++ b/modules/git/diff.go @@ -271,7 +271,17 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi } // GetAffectedFiles returns the affected files between two commits -func GetAffectedFiles(repo *Repository, oldCommitID, newCommitID string, env []string) ([]string, error) { +func GetAffectedFiles(repo *Repository, branchName, oldCommitID, newCommitID string, env []string) ([]string, error) { + if oldCommitID == emptySha1ObjectID.String() || oldCommitID == emptySha256ObjectID.String() { + startCommitID, err := repo.GetCommitBranchStart(env, branchName, newCommitID) + if err != nil { + return nil, err + } + if startCommitID == "" { + return nil, fmt.Errorf("cannot find the start commit of %s", newCommitID) + } + oldCommitID = startCommitID + } stdoutReader, stdoutWriter, err := os.Pipe() if err != nil { log.Error("Unable to create os.Pipe for %s", repo.Path) diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 8c3285769e..9405634df1 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -7,6 +7,7 @@ package git import ( "bytes" "io" + "os" "strconv" "strings" @@ -414,7 +415,7 @@ func (repo *Repository) commitsBefore(id ObjectID, limit int) ([]*Commit, error) commits := make([]*Commit, 0, len(formattedLog)) for _, commit := range formattedLog { - branches, err := repo.getBranches(commit, 2) + branches, err := repo.getBranches(os.Environ(), commit.ID.String(), 2) if err != nil { return nil, err } @@ -437,12 +438,15 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit, return repo.commitsBefore(id, num) } -func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) { +func (repo *Repository) getBranches(env []string, commitID string, limit int) ([]string, error) { if DefaultFeatures().CheckVersionAtLeast("2.7.0") { stdout, _, err := NewCommand(repo.Ctx, "for-each-ref", "--format=%(refname:strip=2)"). AddOptionFormat("--count=%d", limit). - AddOptionValues("--contains", commit.ID.String(), BranchPrefix). - RunStdString(&RunOpts{Dir: repo.Path}) + AddOptionValues("--contains", commitID, BranchPrefix). + RunStdString(&RunOpts{ + Dir: repo.Path, + Env: env, + }) if err != nil { return nil, err } @@ -451,7 +455,10 @@ func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) return branches, nil } - stdout, _, err := NewCommand(repo.Ctx, "branch").AddOptionValues("--contains", commit.ID.String()).RunStdString(&RunOpts{Dir: repo.Path}) + stdout, _, err := NewCommand(repo.Ctx, "branch").AddOptionValues("--contains", commitID).RunStdString(&RunOpts{ + Dir: repo.Path, + Env: env, + }) if err != nil { return nil, err } @@ -513,3 +520,35 @@ func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error } return nil } + +func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID string) (string, error) { + cmd := NewCommand(repo.Ctx, "log", prettyLogFormat) + cmd.AddDynamicArguments(endCommitID) + + stdout, _, runErr := cmd.RunStdBytes(&RunOpts{ + Dir: repo.Path, + Env: env, + }) + if runErr != nil { + return "", runErr + } + + parts := bytes.Split(bytes.TrimSpace(stdout), []byte{'\n'}) + + var startCommitID string + for _, commitID := range parts { + branches, err := repo.getBranches(env, string(commitID), 2) + if err != nil { + return "", err + } + for _, b := range branches { + if b != branch { + return startCommitID, nil + } + } + + startCommitID = string(commitID) + } + + return "", nil +} diff --git a/modules/git/repo_commit_test.go b/modules/git/repo_commit_test.go index fee145e924..19983b47b1 100644 --- a/modules/git/repo_commit_test.go +++ b/modules/git/repo_commit_test.go @@ -4,6 +4,7 @@ package git import ( + "os" "path/filepath" "testing" @@ -31,7 +32,7 @@ func TestRepository_GetCommitBranches(t *testing.T) { for _, testCase := range testCases { commit, err := bareRepo1.GetCommit(testCase.CommitID) assert.NoError(t, err) - branches, err := bareRepo1.getBranches(commit, 2) + branches, err := bareRepo1.getBranches(os.Environ(), commit.ID.String(), 2) assert.NoError(t, err) assert.Equal(t, testCase.ExpectedBranches, branches) } |