Browse Source

New push to base repo of base branch: retest all corresponding patches

Unknwon 9 years ago
parent
commit
2be5837cb0
2 changed files with 69 additions and 29 deletions
  1. 61 28
      models/pull.go
  2. 8 1
      models/webhook.go

+ 61 - 28
models/pull.go

@@ -206,6 +206,12 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
 	return sess.Commit()
 }
 
+// patchConflicts is a list of conflit description from Git.
+var patchConflicts = []string{
+	"patch does not apply",
+	"already exists in working directory",
+}
+
 // testPatch checks if patch can be merged to base repository without conflit.
 func (pr *PullRequest) testPatch() (err error) {
 	if pr.BaseRepo == nil {
@@ -231,12 +237,15 @@ func (pr *PullRequest) testPatch() (err error) {
 		fmt.Sprintf("testPatch(git apply --check): %d", pr.BaseRepo.ID),
 		"git", "apply", "--check", patchPath)
 	if err != nil {
-		if strings.Contains(stderr, "patch does not apply") {
-			log.Trace("PullRequest[%d].testPatch(apply): has conflit", pr.ID)
-			pr.Status = PULL_REQUEST_STATUS_CONFLICT
-		} else {
-			return fmt.Errorf("git apply --check: %v - %s", err, stderr)
+		for i := range patchConflicts {
+			if strings.Contains(stderr, patchConflicts[i]) {
+				log.Trace("PullRequest[%d].testPatch(apply): has conflit", pr.ID)
+				pr.Status = PULL_REQUEST_STATUS_CONFLICT
+				return nil
+			}
 		}
+
+		return fmt.Errorf("git apply --check: %v - %s", err, stderr)
 	}
 	return nil
 }
@@ -269,6 +278,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
 		return err
 	}
 
+	pr.Index = pull.Index
 	if err = repo.SavePatch(pr.Index, patch); err != nil {
 		return fmt.Errorf("SavePatch: %v", err)
 	}
@@ -282,7 +292,6 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
 	}
 
 	pr.IssueID = pull.ID
-	pr.Index = pull.Index
 	if _, err = sess.Insert(pr); err != nil {
 		return fmt.Errorf("insert pull repo: %v", err)
 	}
@@ -308,10 +317,19 @@ func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch
 
 // GetUnmergedPullRequestsByHeadInfo returnss all pull requests that are open and has not been merged
 // by given head information (repo and branch).
-func GetUnmergedPullRequestsByHeadInfo(headRepoID int64, headBranch string) ([]*PullRequest, error) {
+func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
 	prs := make([]*PullRequest, 0, 2)
 	return prs, x.Where("head_repo_id=? AND head_branch=? AND has_merged=? AND issue.is_closed=?",
-		headRepoID, headBranch, false, false).
+		repoID, branch, false, false).
+		Join("INNER", "issue", "issue.id=pull_request.issue_id").Find(&prs)
+}
+
+// GetUnmergedPullRequestsByBaseInfo returnss all pull requests that are open and has not been merged
+// by given base information (repo and branch).
+func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) {
+	prs := make([]*PullRequest, 0, 2)
+	return prs, x.Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
+		repoID, branch, false, false).
 		Join("INNER", "issue", "issue.id=pull_request.issue_id").Find(&prs)
 }
 
@@ -371,23 +389,24 @@ func (pr *PullRequest) checkAndUpdateStatus() {
 	}
 }
 
-// AddTestPullRequestTask adds new test tasks by given head repository and head branch,
-// and generate new patch for testing as needed.
-func AddTestPullRequestTask(headRepoID int64, headBranch string) {
-	log.Trace("AddTestPullRequestTask[head_repo_id: %d, head_branch: %s]: finding pull requests", headRepoID, headBranch)
-	prs, err := GetUnmergedPullRequestsByHeadInfo(headRepoID, headBranch)
-	if err != nil {
-		log.Error(4, "Find pull requests[head_repo_id: %d, head_branch: %s]: %v", headRepoID, headBranch, err)
-		return
-	}
+// addToTaskQueue adds itself to pull request test task queue.
+func (pr *PullRequest) addToTaskQueue() {
+	go PullRequestQueue.AddFunc(pr.ID, func() {
+		pr.Status = PULL_REQUEST_STATUS_CHECKING
+		if err := pr.UpdateCols("status"); err != nil {
+			log.Error(5, "addToTaskQueue.UpdateCols[%d].(add to queue): %v", pr.ID, err)
+		}
+	})
+}
 
+func addHeadRepoTasks(prs []*PullRequest) {
 	for _, pr := range prs {
-		log.Trace("AddTestPullRequestTask[%d]: composing new test task", pr.ID)
+		log.Trace("addHeadRepoTasks[%d]: composing new test task", pr.ID)
 		if err := pr.GetHeadRepo(); err != nil {
 			log.Error(4, "GetHeadRepo[%d]: %v", pr.ID, err)
 			continue
 		} else if pr.HeadRepo == nil {
-			log.Trace("AddTestPullRequestTask[%d]: ignored cruppted data", pr.ID)
+			log.Trace("addHeadRepoTasks[%d]: ignored cruppted data", pr.ID)
 			continue
 		}
 
@@ -420,15 +439,29 @@ func AddTestPullRequestTask(headRepoID int64, headBranch string) {
 			continue
 		}
 
-		if !PullRequestQueue.Exist(pr.ID) {
-			go func() {
-				PullRequestQueue.Add(pr.ID)
-				pr.Status = PULL_REQUEST_STATUS_CHECKING
-				if err = pr.UpdateCols("status"); err != nil {
-					log.Error(5, "AddTestPullRequestTask.UpdateCols[%d].(add to queue): %v", pr.ID, err)
-				}
-			}()
-		}
+		pr.addToTaskQueue()
+	}
+}
+
+// AddTestPullRequestTask adds new test tasks by given head/base repository and head/base branch,
+// and generate new patch for testing as needed.
+func AddTestPullRequestTask(repoID int64, branch string) {
+	log.Trace("AddTestPullRequestTask[head_repo_id: %d, head_branch: %s]: finding pull requests", repoID, branch)
+	prs, err := GetUnmergedPullRequestsByHeadInfo(repoID, branch)
+	if err != nil {
+		log.Error(4, "Find pull requests[head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
+		return
+	}
+	addHeadRepoTasks(prs)
+
+	log.Trace("AddTestPullRequestTask[base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch)
+	prs, err = GetUnmergedPullRequestsByBaseInfo(repoID, branch)
+	if err != nil {
+		log.Error(4, "Find pull requests[base_repo_id: %d, base_branch: %s]: %v", repoID, branch, err)
+		return
+	}
+	for _, pr := range prs {
+		pr.addToTaskQueue()
 	}
 }
 

+ 8 - 1
models/webhook.go

@@ -465,7 +465,7 @@ func (q *UniqueQueue) Remove(id interface{}) {
 	delete(q.ids, com.ToStr(id))
 }
 
-func (q *UniqueQueue) Add(id interface{}) {
+func (q *UniqueQueue) AddFunc(id interface{}, fn func()) {
 	newid := com.ToStr(id)
 
 	if q.Exist(id) {
@@ -474,10 +474,17 @@ func (q *UniqueQueue) Add(id interface{}) {
 
 	q.lock.Lock()
 	q.ids[newid] = true
+	if fn != nil {
+		fn()
+	}
 	q.lock.Unlock()
 	q.queue <- newid
 }
 
+func (q *UniqueQueue) Add(id interface{}) {
+	q.AddFunc(id, nil)
+}
+
 func (q *UniqueQueue) Exist(id interface{}) bool {
 	q.lock.Lock()
 	defer q.lock.Unlock()