GitRoot
Craft your forge, Build your project, Grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package repository
6
7import (
8 "errors"
9 "slices"
10
11 "github.com/go-git/go-git/v6/plumbing"
12 "github.com/goccy/go-yaml"
13)
14
15type repoConfiguration struct {
16 DefaultBranch string
17 NoForcePush []string
18 NbMaxBranchesBeforeRejectingAnonymous int
19}
20
21type RepoConfiguration struct {
22 DefaultBranch plumbing.ReferenceName
23 NoForcePush []plumbing.ReferenceName
24 NbMaxBranchesBeforeRejectingAnonymous int
25}
26
27func newRepoConfiguration(defaultBranch string, nbMaxBranchesBeforeRejectingAnonymous int) repoConfiguration {
28 return repoConfiguration{
29 DefaultBranch: defaultBranch,
30 NoForcePush: []string{defaultBranch},
31 NbMaxBranchesBeforeRejectingAnonymous: nbMaxBranchesBeforeRejectingAnonymous,
32 }
33}
34
35func (r repoConfiguration) toFileContent() []byte {
36 content, _ := yaml.Marshal(r)
37 return content
38}
39
40func readRepoConfiguration(fileContent []byte) (RepoConfiguration, error) {
41 repoConf := repoConfiguration{}
42 err := yaml.Unmarshal(fileContent, &repoConf)
43 if err != nil {
44 return RepoConfiguration{}, err
45 }
46 noForcePush := make([]plumbing.ReferenceName, len(repoConf.NoForcePush))
47 for i, rc := range repoConf.NoForcePush {
48 noForcePush[i] = plumbing.NewBranchReferenceName(rc)
49 }
50 return RepoConfiguration{
51 DefaultBranch: plumbing.NewBranchReferenceName(repoConf.DefaultBranch),
52 NoForcePush: noForcePush,
53 NbMaxBranchesBeforeRejectingAnonymous: repoConf.NbMaxBranchesBeforeRejectingAnonymous,
54 }, nil
55}
56
57func (r RepoConfiguration) IsNoPushBranch(branch plumbing.ReferenceName) bool {
58 return slices.Contains(r.NoForcePush, branch)
59}
60
61func (r RepoConfiguration) CanCreateAnonymousBranch(repo *GitRootRepository, globalNbBranches int) error {
62 projectNbBranches := r.NbMaxBranchesBeforeRejectingAnonymous
63 if globalNbBranches == 0 || projectNbBranches == 0 {
64 return errors.New("anonymous branches not allowed")
65 } else if globalNbBranches > 0 || projectNbBranches > 0 {
66 branches, err := repo.Branches()
67 if err != nil {
68 return errors.New("error in couting branches")
69 }
70 goodGlobal := globalNbBranches == -1 || len(branches) < globalNbBranches
71 goodLocal := projectNbBranches == -1 || len(branches) < projectNbBranches
72 if !goodGlobal || !goodLocal {
73 return errors.New("max anonymous branches reach, please retry later")
74 }
75 }
76 return nil
77}