任务详情
任务详情链接
分支保护相关源码逻辑
m.Group("/:username/:reponame", func() {
...
m.Group("/branches", func() {
...
// 设置分支保护的组合路由
m.Combo("/*").Get(repo.SettingsProtectedBranch).
Post(bindIgnErr(form.ProtectBranch{}), repo.SettingsProtectedBranchPost)
}, func(c *context.Context) {
if c.Repo.Repository.IsMirror {
c.NotFound()
return
}
})
}
// GET请求:获取分支保护设置页面
func SettingsProtectedBranch(c *context.Context) {
branch := c.Params("*")
if !c.Repo.GitRepo.HasBranch(branch) {
c.NotFound()
return
}
// 拼凑template html中需要的数据分支名、PageIsSettingsBranches标志位具体怎么用这些数据可以查看对应源码中的html引用数据的地方
c.Data["Title"] = c.Tr("repo.settings.protected_branches") + " - " + branch
c.Data["PageIsSettingsBranches"] = true
protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
if err != nil {
if !db.IsErrBranchNotExist(err) {
c.Error(err, "get protect branch of repository by name")
return
}
// No options found, create defaults.
protectBranch = &db.ProtectBranch{
Name: branch,
}
}
// 下面if内容决定了模版引擎在生成html时候,如果是仓库所属用户为个人,不会有白名单相关的设定
if c.Repo.Owner.IsOrganization() {
users, err := c.Repo.Repository.GetWriters()
if err != nil {
c.Error(err, "get writers")
return
}
c.Data["Users"] = users
c.Data["whitelist_users"] = protectBranch.WhitelistUserIDs
teams, err := c.Repo.Owner.TeamsHaveAccessToRepo(c.Repo.Repository.ID, db.AccessModeWrite)
if err != nil {
c.Error(err, "get teams have access to the repository")
return
}
c.Data["Teams"] = teams
c.Data["whitelist_teams"] = protectBranch.WhitelistTeamIDs
}
c.Data["Branch"] = protectBranch
c.Success(SETTINGS_PROTECTED_BRANCH)
}
// 处理器函数repo.SettingsProtectedBranchPost
func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
// 解析分支名
branch := c.Params("*")
if !c.Repo.GitRepo.HasBranch(branch) {
c.NotFound()
return
}
// 从数据库中获取分支信息
protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
if err != nil {
if !db.IsErrBranchNotExist(err) {
c.Error(err, "get protect branch of repository by name")
return
}
// No options found, create defaults.
protectBranch = &db.ProtectBranch{
RepoID: c.Repo.Repository.ID,
Name: branch,
}
}
// 获取post表单 protected、RequirePullRequest和EnableWhitelist
protectBranch.Protected = f.Protected
protectBranch.RequirePullRequest = f.RequirePullRequest
protectBranch.EnableWhitelist = f.EnableWhitelist
if c.Repo.Owner.IsOrganization() {
// 如果仓库所属用户为组织,用白名用户和白名单团队更新仓库protect信息(数据落地)
err = db.UpdateOrgProtectBranch(c.Repo.Repository, protectBranch, f.WhitelistUsers, f.WhitelistTeams)
} else {
// 其他情况直接更新当前分支为保护分支(数据落地)
err = db.UpdateProtectBranch(protectBranch)
}
if err != nil {
c.Error(err, "update protect branch")
return
}
c.Flash.Success(c.Tr("repo.settings.update_protect_branch_success"))
// 页面302,返回html数据
c.Redirect(fmt.Sprintf("%s/settings/branches/%s", c.Repo.RepoLink, branch))
// 设置落地: 将所属用户为组织的仓库分支保护相关数据,写入到数据库中
func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whitelistUserIDs, whitelistTeamIDs string) (err error) {
// 所属用户非组织或者仓库不存在直接返回函数
if err = repo.GetOwner(); err != nil {
return fmt.Errorf("GetOwner: %v", err)
} else if !repo.Owner.IsOrganization() {
return fmt.Errorf("expect repository owner to be an organization")
}
// 如果提交的和分支db存放的user白名单列表不同,从提交用户中筛选有效用户
if protectBranch.WhitelistUserIDs != whitelistUserIDs {
...
protectBranch.WhitelistUserIDs = strings.Join(tool.Int64sToStrings(validUserIDs), ",")
}
// 如果提交的和分支db存放的team白名单列表不同从提交团队中筛选有效团队
if protectBranch.WhitelistTeamIDs != whitelistTeamIDs {
...
protectBranch.WhitelistTeamIDs = strings.Join(tool.Int64sToStrings(validTeamIDs), ",")
}
...
// 更新保护分支信息
if _, err = sess.ID(protectBranch.ID).AllCols().Update(protectBranch); err != nil {
return fmt.Errorf("Update: %v", err)
}
if hasUsersChanged || hasTeamsChanged {
// 删除保护分支白名单
if _, err = sess.Delete(&ProtectBranchWhitelist{ProtectBranchID: protectBranch.ID}); err != nil {
return fmt.Errorf("delete old protect branch whitelists: %v", err)
// 写入保护分支白名单
} else if _, err = sess.Insert(whitelists); err != nil {
return fmt.Errorf("insert new protect branch whitelists: %v", err)
}
}
}
// UpdateProtectBranch 数据落地操作与上面操作类似,少了白名单信息。
// sess.ID(protectBranch.ID).AllCols().Update(protectBranch)只更新了保护分支信息。
简单总结
- 个人仓库分支保护是针对除开自己的所有用户实行分支保护
- 组织下的仓库(仓库的拥有者是一个组织)分支保护,是针对除开组织下的多个或者单个用户和组织下的一个或多个团队实行分支保护