refactor: git patch apply (#38637) (#38638)

Backport #38637
This commit is contained in:
wxiaoguang
2026-07-27 01:32:02 +08:00
committed by GitHub
parent ccd38f9a70
commit d7bc52beea
4 changed files with 78 additions and 109 deletions
+31 -19
View File
@@ -14,7 +14,7 @@ import (
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
"gitea.dev/modules/reqctx"
"gitea.dev/modules/structs"
"gitea.dev/modules/util"
asymkey_service "gitea.dev/services/asymkey"
@@ -110,31 +110,27 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode
return nil
}
// ApplyDiffPatch applies a patch to the given repository
func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) {
func gitPatchPrepare(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, doer *user_model.User, opts *ApplyDiffPatchOptions) (_ *TemporaryUploadRepository, retErr error) {
err := repo.MustNotBeArchived()
if err != nil {
return nil, err
}
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return nil, err
}
defer closer.Close()
if err := opts.Validate(ctx, repo, gitRepo, doer); err != nil {
return nil, err
}
message := strings.TrimSpace(opts.Message)
t, err := NewTemporaryUploadRepository(repo)
if err != nil {
log.Error("NewTemporaryUploadRepository failed: %v", err)
return nil, fmt.Errorf("NewTemporaryUploadRepository failed: %w", err)
}
defer t.Close()
if err := t.Clone(ctx, opts.OldBranch, true); err != nil {
defer func() {
if retErr != nil {
t.Close()
}
}()
// here must NOT use bare repo, because the following git commands might operate working tree ("--index") directly
if err := t.Clone(ctx, opts.OldBranch, false); err != nil {
return nil, err
}
if err := t.SetDefaultIndex(ctx); err != nil {
@@ -153,7 +149,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
} else {
lastCommitID, err := t.gitRepo.ConvertToGitID(opts.LastCommitID)
if err != nil {
return nil, fmt.Errorf("ApplyPatch: Invalid last commit ID: %w", err)
return nil, fmt.Errorf("invalid last commit ID: %w", err)
}
opts.LastCommitID = lastCommitID.String()
if commit.ID.String() != opts.LastCommitID {
@@ -163,6 +159,20 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
}
}
}
return t, nil
}
// ApplyDiffPatch applies a patch to the given repository
func ApplyDiffPatch(ctx reqctx.RequestContext, repo *repo_model.Repository, doer *user_model.User, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) {
gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo)
if err != nil {
return nil, err
}
t, err := gitPatchPrepare(ctx, repo, gitRepo, doer, opts)
if err != nil {
return nil, err
}
defer t.Close()
cmdApply := gitcmd.NewCommand("apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary")
if git.DefaultFeatures().CheckVersionAtLeast("2.32") {
@@ -175,17 +185,19 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
return nil, fmt.Errorf("git apply error: %w", err)
}
// Now write the tree
return gitPatchCommitPush(ctx, t, repo, doer, opts)
}
func gitPatchCommitPush(ctx context.Context, t *TemporaryUploadRepository, repo *repo_model.Repository, doer *user_model.User, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) {
treeHash, err := t.WriteTree(ctx)
if err != nil {
return nil, err
}
// Now commit the tree
commitOpts := &CommitTreeUserOptions{
ParentCommitID: "HEAD",
TreeHash: treeHash,
CommitMessage: message,
CommitMessage: strings.TrimSpace(opts.Message),
SignOff: opts.Signoff,
DoerUser: doer,
AuthorIdentity: opts.Author,
@@ -206,7 +218,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
return nil, err
}
commit, err = t.GetCommit(commitHash)
commit, err := t.GetCommit(commitHash)
if err != nil {
return nil, err
}