code.gitea.io/gitea@v1.22.3/modules/repository/branch.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repository 5 6 import ( 7 "context" 8 "fmt" 9 10 "code.gitea.io/gitea/models/db" 11 git_model "code.gitea.io/gitea/models/git" 12 repo_model "code.gitea.io/gitea/models/repo" 13 "code.gitea.io/gitea/modules/container" 14 "code.gitea.io/gitea/modules/git" 15 "code.gitea.io/gitea/modules/gitrepo" 16 "code.gitea.io/gitea/modules/log" 17 "code.gitea.io/gitea/modules/timeutil" 18 ) 19 20 // SyncRepoBranches synchronizes branch table with repository branches 21 func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error) { 22 repo, err := repo_model.GetRepositoryByID(ctx, repoID) 23 if err != nil { 24 return 0, err 25 } 26 27 log.Debug("SyncRepoBranches: in Repo[%d:%s]", repo.ID, repo.FullName()) 28 29 gitRepo, err := gitrepo.OpenRepository(ctx, repo) 30 if err != nil { 31 log.Error("OpenRepository[%s]: %w", repo.FullName(), err) 32 return 0, err 33 } 34 defer gitRepo.Close() 35 36 return SyncRepoBranchesWithRepo(ctx, repo, gitRepo, doerID) 37 } 38 39 func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, doerID int64) (int64, error) { 40 objFmt, err := gitRepo.GetObjectFormat() 41 if err != nil { 42 return 0, fmt.Errorf("GetObjectFormat: %w", err) 43 } 44 _, err = db.GetEngine(ctx).ID(repo.ID).Update(&repo_model.Repository{ObjectFormatName: objFmt.Name()}) 45 if err != nil { 46 return 0, fmt.Errorf("UpdateRepository: %w", err) 47 } 48 repo.ObjectFormatName = objFmt.Name() // keep consistent with db 49 50 allBranches := container.Set[string]{} 51 { 52 branches, _, err := gitRepo.GetBranchNames(0, 0) 53 if err != nil { 54 return 0, err 55 } 56 log.Trace("SyncRepoBranches[%s]: branches[%d]: %v", repo.FullName(), len(branches), branches) 57 for _, branch := range branches { 58 allBranches.Add(branch) 59 } 60 } 61 62 dbBranches := make(map[string]*git_model.Branch) 63 { 64 branches, err := db.Find[git_model.Branch](ctx, git_model.FindBranchOptions{ 65 ListOptions: db.ListOptionsAll, 66 RepoID: repo.ID, 67 }) 68 if err != nil { 69 return 0, err 70 } 71 for _, branch := range branches { 72 dbBranches[branch.Name] = branch 73 } 74 } 75 76 var toAdd []*git_model.Branch 77 var toUpdate []*git_model.Branch 78 var toRemove []int64 79 for branch := range allBranches { 80 dbb := dbBranches[branch] 81 commit, err := gitRepo.GetBranchCommit(branch) 82 if err != nil { 83 return 0, err 84 } 85 if dbb == nil { 86 toAdd = append(toAdd, &git_model.Branch{ 87 RepoID: repo.ID, 88 Name: branch, 89 CommitID: commit.ID.String(), 90 CommitMessage: commit.Summary(), 91 PusherID: doerID, 92 CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), 93 }) 94 } else if commit.ID.String() != dbb.CommitID { 95 toUpdate = append(toUpdate, &git_model.Branch{ 96 ID: dbb.ID, 97 RepoID: repo.ID, 98 Name: branch, 99 CommitID: commit.ID.String(), 100 CommitMessage: commit.Summary(), 101 PusherID: doerID, 102 CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), 103 }) 104 } 105 } 106 107 for _, dbBranch := range dbBranches { 108 if !allBranches.Contains(dbBranch.Name) && !dbBranch.IsDeleted { 109 toRemove = append(toRemove, dbBranch.ID) 110 } 111 } 112 113 log.Trace("SyncRepoBranches[%s]: toAdd: %v, toUpdate: %v, toRemove: %v", repo.FullName(), toAdd, toUpdate, toRemove) 114 115 if len(toAdd) == 0 && len(toRemove) == 0 && len(toUpdate) == 0 { 116 return int64(len(allBranches)), nil 117 } 118 119 if err := db.WithTx(ctx, func(ctx context.Context) error { 120 if len(toAdd) > 0 { 121 if err := git_model.AddBranches(ctx, toAdd); err != nil { 122 return err 123 } 124 } 125 126 for _, b := range toUpdate { 127 if _, err := db.GetEngine(ctx).ID(b.ID). 128 Cols("commit_id, commit_message, pusher_id, commit_time, is_deleted"). 129 Update(b); err != nil { 130 return err 131 } 132 } 133 134 if len(toRemove) > 0 { 135 if err := git_model.DeleteBranches(ctx, repo.ID, doerID, toRemove); err != nil { 136 return err 137 } 138 } 139 140 return nil 141 }); err != nil { 142 return 0, err 143 } 144 return int64(len(allBranches)), nil 145 }