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}