Skip to content

Commit f2f0a41

Browse files
committed
Remove SavePatch and generate patches on the fly
1 parent 8ff386b commit f2f0a41

File tree

14 files changed

+377
-457
lines changed

14 files changed

+377
-457
lines changed

models/issue_xref_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ func testCreatePR(t *testing.T, repo, doer int64, title, content string) *PullRe
142142
r := AssertExistsAndLoadBean(t, &Repository{ID: repo}).(*Repository)
143143
d := AssertExistsAndLoadBean(t, &User{ID: doer}).(*User)
144144
i := &Issue{RepoID: r.ID, PosterID: d.ID, Poster: d, Title: title, Content: content, IsPull: true}
145-
pr := &PullRequest{HeadRepoID: repo, BaseRepoID: repo, HeadBranch: "head", BaseBranch: "base"}
146-
assert.NoError(t, NewPullRequest(r, i, nil, nil, pr, 0, "unknown"))
145+
pr := &PullRequest{HeadRepoID: repo, BaseRepoID: repo, HeadBranch: "head", BaseBranch: "base", Status: PullRequestStatusMergeable}
146+
assert.NoError(t, NewPullRequest(r, i, nil, nil, pr))
147147
pr.Issue = i
148148
return pr
149149
}

models/pull.go

Lines changed: 3 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,16 @@
66
package models
77

88
import (
9-
"bufio"
109
"fmt"
11-
"io/ioutil"
1210
"os"
1311
"path"
14-
"path/filepath"
15-
"strconv"
1612
"strings"
17-
"time"
1813

1914
"code.gitea.io/gitea/modules/git"
2015
"code.gitea.io/gitea/modules/log"
2116
"code.gitea.io/gitea/modules/setting"
2217
api "code.gitea.io/gitea/modules/structs"
2318
"code.gitea.io/gitea/modules/timeutil"
24-
25-
"github.com/unknwon/com"
2619
)
2720

2821
// PullRequestType defines pull request type
@@ -482,125 +475,12 @@ func (pr *PullRequest) SetMerged() (err error) {
482475
return nil
483476
}
484477

485-
// patchConflicts is a list of conflict description from Git.
486-
var patchConflicts = []string{
487-
"patch does not apply",
488-
"already exists in working directory",
489-
"unrecognized input",
490-
"error:",
491-
}
492-
493-
// TestPatch checks if patch can be merged to base repository without conflict.
494-
func (pr *PullRequest) TestPatch() error {
495-
return pr.testPatch(x)
496-
}
497-
498-
// testPatch checks if patch can be merged to base repository without conflict.
499-
func (pr *PullRequest) testPatch(e Engine) (err error) {
500-
if pr.BaseRepo == nil {
501-
pr.BaseRepo, err = getRepositoryByID(e, pr.BaseRepoID)
502-
if err != nil {
503-
return fmt.Errorf("GetRepositoryByID: %v", err)
504-
}
505-
}
506-
507-
patchPath, err := pr.BaseRepo.patchPath(e, pr.Index)
508-
if err != nil {
509-
return fmt.Errorf("BaseRepo.PatchPath: %v", err)
510-
}
511-
512-
// Fast fail if patch does not exist, this assumes data is corrupted.
513-
if !com.IsFile(patchPath) {
514-
log.Trace("PullRequest[%d].testPatch: ignored corrupted data", pr.ID)
515-
return nil
516-
}
517-
518-
RepoWorkingPool.CheckIn(com.ToStr(pr.BaseRepoID))
519-
defer RepoWorkingPool.CheckOut(com.ToStr(pr.BaseRepoID))
520-
521-
log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
522-
523-
pr.Status = PullRequestStatusChecking
524-
525-
indexTmpPath := filepath.Join(os.TempDir(), "gitea-"+pr.BaseRepo.Name+"-"+strconv.Itoa(time.Now().Nanosecond()))
526-
defer os.Remove(indexTmpPath)
527-
528-
_, err = git.NewCommand("read-tree", pr.BaseBranch).RunInDirWithEnv("", []string{"GIT_DIR=" + pr.BaseRepo.RepoPath(), "GIT_INDEX_FILE=" + indexTmpPath})
529-
if err != nil {
530-
return fmt.Errorf("git read-tree --index-output=%s %s: %v", indexTmpPath, pr.BaseBranch, err)
531-
}
532-
533-
prUnit, err := pr.BaseRepo.getUnit(e, UnitTypePullRequests)
534-
if err != nil {
535-
return err
536-
}
537-
prConfig := prUnit.PullRequestsConfig()
538-
539-
args := []string{"apply", "--check", "--cached"}
540-
if prConfig.IgnoreWhitespaceConflicts {
541-
args = append(args, "--ignore-whitespace")
542-
}
543-
args = append(args, patchPath)
544-
pr.ConflictedFiles = []string{}
545-
546-
stderrBuilder := new(strings.Builder)
547-
err = git.NewCommand(args...).RunInDirTimeoutEnvPipeline(
548-
[]string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()},
549-
-1,
550-
"",
551-
nil,
552-
stderrBuilder)
553-
stderr := stderrBuilder.String()
554-
555-
if err != nil {
556-
for i := range patchConflicts {
557-
if strings.Contains(stderr, patchConflicts[i]) {
558-
log.Trace("PullRequest[%d].testPatch (apply): has conflict: %s", pr.ID, stderr)
559-
const prefix = "error: patch failed:"
560-
pr.Status = PullRequestStatusConflict
561-
pr.ConflictedFiles = make([]string, 0, 5)
562-
scanner := bufio.NewScanner(strings.NewReader(stderr))
563-
for scanner.Scan() {
564-
line := scanner.Text()
565-
566-
if strings.HasPrefix(line, prefix) {
567-
var found bool
568-
var filepath = strings.TrimSpace(strings.Split(line[len(prefix):], ":")[0])
569-
for _, f := range pr.ConflictedFiles {
570-
if f == filepath {
571-
found = true
572-
break
573-
}
574-
}
575-
if !found {
576-
pr.ConflictedFiles = append(pr.ConflictedFiles, filepath)
577-
}
578-
}
579-
// only list 10 conflicted files
580-
if len(pr.ConflictedFiles) >= 10 {
581-
break
582-
}
583-
}
584-
585-
if len(pr.ConflictedFiles) > 0 {
586-
log.Trace("Found %d files conflicted: %v", len(pr.ConflictedFiles), pr.ConflictedFiles)
587-
}
588-
589-
return nil
590-
}
591-
}
592-
593-
return fmt.Errorf("git apply --check: %v - %s", err, stderr)
594-
}
595-
return nil
596-
}
597-
598478
// NewPullRequest creates new pull request with labels for repository.
599-
func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []string, pr *PullRequest, patchFileSize int64, patchFileName string) (err error) {
479+
func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []string, pr *PullRequest) (err error) {
600480
// Retry several times in case INSERT fails due to duplicate key for (repo_id, index); see #7887
601481
i := 0
602482
for {
603-
if err = newPullRequestAttempt(repo, pull, labelIDs, uuids, pr, patchFileSize, patchFileName); err == nil {
483+
if err = newPullRequestAttempt(repo, pull, labelIDs, uuids, pr); err == nil {
604484
return nil
605485
}
606486
if !IsErrNewIssueInsert(err) {
@@ -614,7 +494,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
614494
return fmt.Errorf("NewPullRequest: too many errors attempting to insert the new issue. Last error was: %v", err)
615495
}
616496

617-
func newPullRequestAttempt(repo *Repository, pull *Issue, labelIDs []int64, uuids []string, pr *PullRequest, patchFileSize int64, patchFileName string) (err error) {
497+
func newPullRequestAttempt(repo *Repository, pull *Issue, labelIDs []int64, uuids []string, pr *PullRequest) (err error) {
618498
sess := x.NewSession()
619499
defer sess.Close()
620500
if err = sess.Begin(); err != nil {
@@ -636,20 +516,6 @@ func newPullRequestAttempt(repo *Repository, pull *Issue, labelIDs []int64, uuid
636516

637517
pr.Index = pull.Index
638518
pr.BaseRepo = repo
639-
pr.Status = PullRequestStatusChecking
640-
if patchFileSize > 0 {
641-
if err = repo.savePatch(sess, pr.Index, patchFileName); err != nil {
642-
return fmt.Errorf("SavePatch: %v", err)
643-
}
644-
645-
if err = pr.testPatch(sess); err != nil {
646-
return fmt.Errorf("testPatch: %v", err)
647-
}
648-
}
649-
// No conflict appears after test means mergeable.
650-
if pr.Status == PullRequestStatusChecking {
651-
pr.Status = PullRequestStatusMergeable
652-
}
653519

654520
pr.IssueID = pull.ID
655521
if _, err = sess.Insert(pr); err != nil {
@@ -765,65 +631,6 @@ func (pr *PullRequest) UpdateCols(cols ...string) error {
765631
return err
766632
}
767633

768-
// UpdatePatch generates and saves a new patch.
769-
func (pr *PullRequest) UpdatePatch() (err error) {
770-
if err = pr.GetHeadRepo(); err != nil {
771-
return fmt.Errorf("GetHeadRepo: %v", err)
772-
} else if pr.HeadRepo == nil {
773-
log.Trace("PullRequest[%d].UpdatePatch: ignored corrupted data", pr.ID)
774-
return nil
775-
}
776-
777-
if err = pr.GetBaseRepo(); err != nil {
778-
return fmt.Errorf("GetBaseRepo: %v", err)
779-
}
780-
781-
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
782-
if err != nil {
783-
return fmt.Errorf("OpenRepository: %v", err)
784-
}
785-
defer headGitRepo.Close()
786-
787-
// Add a temporary remote.
788-
tmpRemote := com.ToStr(time.Now().UnixNano())
789-
if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name), true); err != nil {
790-
return fmt.Errorf("AddRemote: %v", err)
791-
}
792-
defer func() {
793-
if err := headGitRepo.RemoveRemote(tmpRemote); err != nil {
794-
log.Error("UpdatePatch: RemoveRemote: %s", err)
795-
}
796-
}()
797-
pr.MergeBase, _, err = headGitRepo.GetMergeBase(tmpRemote, pr.BaseBranch, pr.HeadBranch)
798-
if err != nil {
799-
return fmt.Errorf("GetMergeBase: %v", err)
800-
} else if err = pr.Update(); err != nil {
801-
return fmt.Errorf("Update: %v", err)
802-
}
803-
804-
tmpPatchFile, err := ioutil.TempFile("", "patch")
805-
if err != nil {
806-
log.Error("Unable to create temporary patch file! Error: %v", err)
807-
return fmt.Errorf("Unable to create temporary patch file! Error: %v", err)
808-
}
809-
defer func() {
810-
_ = os.Remove(tmpPatchFile.Name())
811-
}()
812-
813-
if err := headGitRepo.GetPatch(pr.MergeBase, pr.HeadBranch, tmpPatchFile); err != nil {
814-
tmpPatchFile.Close()
815-
log.Error("Unable to get patch file from %s to %s in %s/%s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name, err)
816-
return fmt.Errorf("Unable to get patch file from %s to %s in %s/%s Error: %v", pr.MergeBase, pr.HeadBranch, pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name, err)
817-
}
818-
819-
tmpPatchFile.Close()
820-
if err = pr.BaseRepo.SavePatch(pr.Index, tmpPatchFile.Name()); err != nil {
821-
return fmt.Errorf("BaseRepo.SavePatch: %v", err)
822-
}
823-
824-
return nil
825-
}
826-
827634
// PushToBaseRepo pushes commits from branches of head repository to
828635
// corresponding branches of base repository.
829636
// FIXME: Only push branches that are actually updates?

models/pull_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,6 @@ func TestPullRequest_UpdateCols(t *testing.T) {
190190
CheckConsistencyFor(t, pr)
191191
}
192192

193-
// TODO TestPullRequest_UpdatePatch
194-
195193
// TODO TestPullRequest_PushToBaseRepo
196194

197195
func TestPullRequestList_LoadAttributes(t *testing.T) {

models/repo.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
// Needed for jpeg support
1616
_ "image/jpeg"
1717
"image/png"
18-
"io"
1918
"io/ioutil"
2019
"net/url"
2120
"os"
@@ -888,53 +887,6 @@ func (repo *Repository) DescriptionHTML() template.HTML {
888887
return template.HTML(markup.Sanitize(string(desc)))
889888
}
890889

891-
// PatchPath returns corresponding patch file path of repository by given issue ID.
892-
func (repo *Repository) PatchPath(index int64) (string, error) {
893-
return repo.patchPath(x, index)
894-
}
895-
896-
func (repo *Repository) patchPath(e Engine, index int64) (string, error) {
897-
if err := repo.getOwner(e); err != nil {
898-
return "", err
899-
}
900-
901-
return filepath.Join(RepoPath(repo.Owner.Name, repo.Name), "pulls", com.ToStr(index)+".patch"), nil
902-
}
903-
904-
// SavePatch saves patch data to corresponding location by given issue ID.
905-
func (repo *Repository) SavePatch(index int64, name string) error {
906-
return repo.savePatch(x, index, name)
907-
}
908-
909-
func (repo *Repository) savePatch(e Engine, index int64, name string) error {
910-
patchPath, err := repo.patchPath(e, index)
911-
if err != nil {
912-
return fmt.Errorf("PatchPath: %v", err)
913-
}
914-
dir := filepath.Dir(patchPath)
915-
916-
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
917-
return fmt.Errorf("Failed to create dir %s: %v", dir, err)
918-
}
919-
920-
inputFile, err := os.Open(name)
921-
if err != nil {
922-
return fmt.Errorf("Couldn't open temporary patch file: %s", err)
923-
}
924-
outputFile, err := os.Create(patchPath)
925-
if err != nil {
926-
inputFile.Close()
927-
return fmt.Errorf("Couldn't open destination patch file: %s", err)
928-
}
929-
defer outputFile.Close()
930-
_, err = io.Copy(outputFile, inputFile)
931-
inputFile.Close()
932-
if err != nil {
933-
return fmt.Errorf("Writing to patch file failed: %s", err)
934-
}
935-
return nil
936-
}
937-
938890
func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) {
939891
has, err := e.Get(&Repository{
940892
OwnerID: u.ID,

modules/git/repo_compare.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package git
77

88
import (
9-
"bytes"
109
"container/list"
1110
"fmt"
1211
"io"
@@ -94,19 +93,22 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string)
9493
return compareInfo, nil
9594
}
9695

97-
// GetPatch generates and returns patch data between given revisions.
98-
func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
99-
return NewCommand("diff", "-p", "--binary", base, head).RunInDirPipeline(repo.Path, w, nil)
96+
// GetDiffOrPatch generates either diff or formatted patch data between given revisions
97+
func (repo *Repository) GetDiffOrPatch(base, head string, w io.Writer, formatted bool) error {
98+
if formatted {
99+
return repo.GetPatch(base, head, w)
100+
}
101+
return repo.GetDiff(base, head, w)
100102
}
101103

102-
// GetFormatPatch generates and returns format-patch data between given revisions.
103-
func (repo *Repository) GetFormatPatch(base, head string) (io.Reader, error) {
104-
stdout := new(bytes.Buffer)
105-
stderr := new(bytes.Buffer)
104+
// GetDiff generates and returns patch data between given revisions.
105+
func (repo *Repository) GetDiff(base, head string, w io.Writer) error {
106+
return NewCommand("diff", "-p", "--binary", base, head).
107+
RunInDirPipeline(repo.Path, w, nil)
108+
}
106109

107-
if err := NewCommand("format-patch", "--binary", "--stdout", base+"..."+head).
108-
RunInDirPipeline(repo.Path, stdout, stderr); err != nil {
109-
return nil, concatenateError(err, stderr.String())
110-
}
111-
return stdout, nil
110+
// GetPatch generates and returns format-patch data between given revisions.
111+
func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
112+
return NewCommand("format-patch", "--binary", "--stdout", base+"..."+head).
113+
RunInDirPipeline(repo.Path, w, nil)
112114
}

modules/git/repo_compare_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package git
66

77
import (
8+
"bytes"
89
"io/ioutil"
910
"os"
1011
"path/filepath"
@@ -21,7 +22,8 @@ func TestGetFormatPatch(t *testing.T) {
2122
repo, err := OpenRepository(clonedPath)
2223
assert.NoError(t, err)
2324
defer repo.Close()
24-
rd, err := repo.GetFormatPatch("8d92fc95^", "8d92fc95")
25+
rd := &bytes.Buffer{}
26+
err = repo.GetPatch("8d92fc95^", "8d92fc95", rd)
2527
assert.NoError(t, err)
2628
patchb, err := ioutil.ReadAll(rd)
2729
assert.NoError(t, err)

0 commit comments

Comments
 (0)