mirror of https://github.com/go-gitea/gitea.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.9 KiB
146 lines
3.9 KiB
// Copyright 2023 The Gitea Authors. All rights reserved. |
|
// SPDX-License-Identifier: MIT |
|
|
|
package repository |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
|
|
"code.gitea.io/gitea/models/db" |
|
git_model "code.gitea.io/gitea/models/git" |
|
repo_model "code.gitea.io/gitea/models/repo" |
|
"code.gitea.io/gitea/modules/container" |
|
"code.gitea.io/gitea/modules/git" |
|
"code.gitea.io/gitea/modules/gitrepo" |
|
"code.gitea.io/gitea/modules/log" |
|
"code.gitea.io/gitea/modules/timeutil" |
|
) |
|
|
|
// SyncRepoBranches synchronizes branch table with repository branches |
|
func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error) { |
|
repo, err := repo_model.GetRepositoryByID(ctx, repoID) |
|
if err != nil { |
|
return 0, err |
|
} |
|
|
|
log.Debug("SyncRepoBranches: in Repo[%d:%s]", repo.ID, repo.FullName()) |
|
|
|
gitRepo, err := gitrepo.OpenRepository(ctx, repo) |
|
if err != nil { |
|
log.Error("OpenRepository[%s]: %w", repo.FullName(), err) |
|
return 0, err |
|
} |
|
defer gitRepo.Close() |
|
|
|
return SyncRepoBranchesWithRepo(ctx, repo, gitRepo, doerID) |
|
} |
|
|
|
func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, doerID int64) (int64, error) { |
|
objFmt, err := gitRepo.GetObjectFormat() |
|
if err != nil { |
|
return 0, fmt.Errorf("GetObjectFormat: %w", err) |
|
} |
|
if objFmt.Name() != repo.ObjectFormatName { |
|
repo.ObjectFormatName = objFmt.Name() |
|
if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "object_format_name"); err != nil { |
|
return 0, fmt.Errorf("UpdateRepositoryColsWithAutoTime: %w", err) |
|
} |
|
} |
|
|
|
allBranches := container.Set[string]{} |
|
{ |
|
branches, _, err := gitRepo.GetBranchNames(0, 0) |
|
if err != nil { |
|
return 0, err |
|
} |
|
log.Trace("SyncRepoBranches[%s]: branches[%d]: %v", repo.FullName(), len(branches), branches) |
|
for _, branch := range branches { |
|
allBranches.Add(branch) |
|
} |
|
} |
|
|
|
dbBranches := make(map[string]*git_model.Branch) |
|
{ |
|
branches, err := db.Find[git_model.Branch](ctx, git_model.FindBranchOptions{ |
|
ListOptions: db.ListOptionsAll, |
|
RepoID: repo.ID, |
|
}) |
|
if err != nil { |
|
return 0, err |
|
} |
|
for _, branch := range branches { |
|
dbBranches[branch.Name] = branch |
|
} |
|
} |
|
|
|
var toAdd []*git_model.Branch |
|
var toUpdate []*git_model.Branch |
|
var toRemove []int64 |
|
for branch := range allBranches { |
|
dbb := dbBranches[branch] |
|
commit, err := gitRepo.GetBranchCommit(branch) |
|
if err != nil { |
|
return 0, err |
|
} |
|
if dbb == nil { |
|
toAdd = append(toAdd, &git_model.Branch{ |
|
RepoID: repo.ID, |
|
Name: branch, |
|
CommitID: commit.ID.String(), |
|
CommitMessage: commit.Summary(), |
|
PusherID: doerID, |
|
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), |
|
}) |
|
} else if commit.ID.String() != dbb.CommitID { |
|
toUpdate = append(toUpdate, &git_model.Branch{ |
|
ID: dbb.ID, |
|
RepoID: repo.ID, |
|
Name: branch, |
|
CommitID: commit.ID.String(), |
|
CommitMessage: commit.Summary(), |
|
PusherID: doerID, |
|
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), |
|
}) |
|
} |
|
} |
|
|
|
for _, dbBranch := range dbBranches { |
|
if !allBranches.Contains(dbBranch.Name) && !dbBranch.IsDeleted { |
|
toRemove = append(toRemove, dbBranch.ID) |
|
} |
|
} |
|
|
|
log.Trace("SyncRepoBranches[%s]: toAdd: %v, toUpdate: %v, toRemove: %v", repo.FullName(), toAdd, toUpdate, toRemove) |
|
|
|
if len(toAdd) == 0 && len(toRemove) == 0 && len(toUpdate) == 0 { |
|
return int64(len(allBranches)), nil |
|
} |
|
|
|
if err := db.WithTx(ctx, func(ctx context.Context) error { |
|
if len(toAdd) > 0 { |
|
if err := git_model.AddBranches(ctx, toAdd); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
for _, b := range toUpdate { |
|
if _, err := db.GetEngine(ctx).ID(b.ID). |
|
Cols("commit_id, commit_message, pusher_id, commit_time, is_deleted"). |
|
Update(b); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
if len(toRemove) > 0 { |
|
if err := git_model.DeleteBranches(ctx, repo.ID, doerID, toRemove); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
}); err != nil { |
|
return 0, err |
|
} |
|
return int64(len(allBranches)), nil |
|
}
|
|
|