func CalculateCommitsDiff()

in backend/plugins/refdiff/tasks/commit_diff_calculator.go [32:192]


func CalculateCommitsDiff(taskCtx plugin.SubTaskContext) errors.Error {
	data := taskCtx.GetData().(*RefdiffTaskData)
	repoId := data.Options.RepoId
	db := taskCtx.GetDal()
	ctx := taskCtx.GetContext()
	logger := taskCtx.GetLogger()

	if data.Options.ProjectName != "" {
		return nil
	}

	// get all data from finish_commits_diffs
	commitPairsSrc := data.Options.AllPairs
	var commitPairs models.RefCommitPairs
	refCommit := &code.RefCommit{}
	for _, pair := range commitPairsSrc {
		newRefId := fmt.Sprintf("%s:%s", repoId, pair[2])
		oldRefId := fmt.Sprintf("%s:%s", repoId, pair[3])

		count, err := db.Count(
			dal.Select("*"),
			dal.From("_tool_refdiff_finished_commits_diffs"),
			dal.Where("new_commit_sha = ? and old_commit_sha = ?", pair[0], pair[1]))
		if err != nil {
			return err
		}
		if count == 0 {
			commitPairs = append(commitPairs, pair)
		}
		if pair[2] != newRefId || pair[3] != oldRefId {
			refCommit.NewCommitSha = pair[0]
			refCommit.OldCommitSha = pair[1]
			refCommit.NewRefId = newRefId
			refCommit.OldRefId = oldRefId
		}
	}

	if len(commitPairs) == 0 {
		logger.Info("commit pair has been produced.")
		return nil
	}

	commitNodeGraph := utils.NewCommitNodeGraph()
	// mysql limit
	insertCountLimitOfCommitsDiff := int(65535 / reflect.ValueOf(code.CommitsDiff{}).NumField())

	// load commits from db
	cursor, err := db.Cursor(
		dal.Select("cp.*"),
		dal.Join("LEFT JOIN repo_commits rc ON (rc.commit_sha = cp.commit_sha)"),
		dal.From("commit_parents cp"),
		dal.Where("rc.repo_id = ?", repoId),
	)
	if err != nil {
		return err
	}
	defer cursor.Close()

	for cursor.Next() {
		select {
		case <-ctx.Done():
			return errors.Convert(ctx.Err())
		default:
		}
		commitParent := &code.CommitParent{}
		err = db.Fetch(cursor, commitParent)
		if err != nil {
			return errors.Default.Wrap(err, "failed to read commit from database")
		}
		commitNodeGraph.AddParent(commitParent.CommitSha, commitParent.ParentCommitSha)
	}

	logger.Info("Create a commit node graph with node count[%d]", commitNodeGraph.Size())

	// calculate diffs for commits pairs and store them into database
	commitsDiff := &code.CommitsDiff{}
	finishedCommitDiff := &models.FinishedCommitsDiff{}
	lenCommitPairs := len(commitPairs)
	taskCtx.SetProgress(0, lenCommitPairs)

	for _, pair := range commitPairs {
		select {
		case <-ctx.Done():
			return errors.Convert(ctx.Err())
		default:
		}
		// ref might advance, keep commit sha for debugging
		commitsDiff.NewCommitSha = pair[0]
		commitsDiff.OldCommitSha = pair[1]

		finishedCommitDiff.NewCommitSha = pair[0]
		finishedCommitDiff.OldCommitSha = pair[1]

		if commitsDiff.NewCommitSha == commitsDiff.OldCommitSha {
			// different refs might point to a same commit, it is ok
			logger.Info(
				"skipping ref pair due to they are the same %s",
				commitsDiff.NewCommitSha,
			)
			continue
		}

		lostSha, oldCount, newCount := commitNodeGraph.CalculateLostSha(pair[1], pair[0])

		commitsDiffs := []code.CommitsDiff{}
		refCommits := []code.RefCommit{}
		finishedCommitDiffs := []models.FinishedCommitsDiff{}

		commitsDiff.SortingIndex = 1
		for _, sha := range lostSha {
			commitsDiff.CommitSha = sha
			commitsDiffs = append(commitsDiffs, *commitsDiff)

			// sql limit placeholders count only 65535
			if commitsDiff.SortingIndex%insertCountLimitOfCommitsDiff == 0 {
				logger.Info("commitsDiffs count in limited[%d] index[%d]--exec and clean", len(commitsDiffs), commitsDiff.SortingIndex)
				err = db.CreateIfNotExist(commitsDiffs)
				if err != nil {
					return err
				}
				commitsDiffs = []code.CommitsDiff{}
			}

			commitsDiff.SortingIndex++
		}

		if len(commitsDiffs) > 0 {
			logger.Info("insert data count [%d]", len(commitsDiffs))
			err = db.CreateIfNotExist(commitsDiffs)
			if err != nil {
				return err
			}
		}

		refCommits = append(refCommits, *refCommit)
		if len(refCommits) > 0 {
			err = db.CreateIfNotExist(refCommits)
			if err != nil {
				return err
			}
		}

		finishedCommitDiffs = append(finishedCommitDiffs, *finishedCommitDiff)
		if len(finishedCommitDiffs) > 0 {
			err = db.CreateIfNotExist(finishedCommitDiffs)
			if err != nil {
				return err
			}
		}

		logger.Info(
			"total %d commits of difference found between [new][%s] and [old][%s(total:%d)]",
			newCount,
			commitsDiff.NewCommitSha,
			commitsDiff.OldCommitSha,
			oldCount,
		)
		taskCtx.IncProgress(1)
	}
	return nil
}