mirror of
https://github.com/go-gitea/gitea.git
synced 2025-12-22 18:35:32 +01:00
76 lines
2.1 KiB
Go
76 lines
2.1 KiB
Go
// Copyright 2024 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package common
|
|
|
|
import (
|
|
"context"
|
|
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/git"
|
|
pull_service "code.gitea.io/gitea/services/pull"
|
|
)
|
|
|
|
// CompareInfo represents the collected results from ParseCompareInfo
|
|
type CompareInfo struct {
|
|
HeadUser *user_model.User
|
|
HeadRepo *repo_model.Repository
|
|
HeadGitRepo *git.Repository
|
|
CompareInfo *pull_service.CompareInfo
|
|
BaseBranch string
|
|
HeadBranch string
|
|
DirectComparison bool
|
|
}
|
|
|
|
// maxForkTraverseLevel defines the maximum levels to traverse when searching for the head repository.
|
|
const maxForkTraverseLevel = 10
|
|
|
|
// FindHeadRepo tries to find the head repository based on the base repository and head user ID.
|
|
func FindHeadRepo(ctx context.Context, baseRepo *repo_model.Repository, headUserID int64) (*repo_model.Repository, error) {
|
|
if baseRepo.IsFork {
|
|
curRepo := baseRepo
|
|
for curRepo.OwnerID != headUserID { // We assume the fork deepth is not too deep.
|
|
if err := curRepo.GetBaseRepo(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
if curRepo.BaseRepo == nil {
|
|
return findHeadRepoFromRootBase(ctx, curRepo, headUserID, maxForkTraverseLevel)
|
|
}
|
|
curRepo = curRepo.BaseRepo
|
|
}
|
|
return curRepo, nil
|
|
}
|
|
|
|
return findHeadRepoFromRootBase(ctx, baseRepo, headUserID, maxForkTraverseLevel)
|
|
}
|
|
|
|
func findHeadRepoFromRootBase(ctx context.Context, baseRepo *repo_model.Repository, headUserID int64, traverseLevel int) (*repo_model.Repository, error) {
|
|
if traverseLevel == 0 {
|
|
return nil, nil
|
|
}
|
|
// test if we are lucky
|
|
repo, err := repo_model.GetUserFork(ctx, baseRepo.ID, headUserID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if repo != nil {
|
|
return repo, nil
|
|
}
|
|
|
|
firstLevelForkedRepos, err := repo_model.GetRepositoriesByForkID(ctx, baseRepo.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, repo := range firstLevelForkedRepos {
|
|
forked, err := findHeadRepoFromRootBase(ctx, repo, headUserID, traverseLevel-1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if forked != nil {
|
|
return forked, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|