Skip to content

Commit c5fb6fb

Browse files
committed
refactor: house cleaning
rename DestinationURL to DestinationPath Use channels everywhere for error aggregation Improve some conditionnal statements
1 parent 999ccc3 commit c5fb6fb

File tree

5 files changed

+55
-48
lines changed

5 files changed

+55
-48
lines changed

mirroring/get.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ func (g *GitlabInstance) fetchProjects(projectFilters *map[string]bool, groupFil
6767

6868
// Add the project to the mirror mapping
6969
mirrorMapping.AddProject(project.PathWithNamespace, &utils.ProjectMirroringOptions{
70-
CI_CD_Catalog: groupCreationOptions.CI_CD_Catalog,
71-
Issues: groupCreationOptions.Issues,
72-
DestinationURL: filepath.Join(groupCreationOptions.DestinationURL, relativePath),
70+
CI_CD_Catalog: groupCreationOptions.CI_CD_Catalog,
71+
Issues: groupCreationOptions.Issues,
72+
DestinationPath: filepath.Join(groupCreationOptions.DestinationPath, relativePath),
7373
})
7474
}
7575
break
@@ -143,9 +143,9 @@ func (g *GitlabInstance) fetchGroups(groupFilters *map[string]bool, mirrorMappin
143143

144144
// Add the group to the mirror mapping
145145
mirrorMapping.AddGroup(group.FullPath, &utils.GroupMirroringOptions{
146-
CI_CD_Catalog: groupCreationOptions.CI_CD_Catalog,
147-
Issues: groupCreationOptions.Issues,
148-
DestinationURL: filepath.Join(groupCreationOptions.DestinationURL, relativePath),
146+
CI_CD_Catalog: groupCreationOptions.CI_CD_Catalog,
147+
Issues: groupCreationOptions.Issues,
148+
DestinationPath: filepath.Join(groupCreationOptions.DestinationPath, relativePath),
149149
})
150150
}
151151
break

mirroring/instance.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,5 @@ func (g *GitlabInstance) addGroup(groupPath string, group *gitlab.Group) {
5858
func (g *GitlabInstance) getGroup(groupPath string) *gitlab.Group {
5959
g.muGroups.RLock()
6060
defer g.muGroups.RUnlock()
61-
var group *gitlab.Group
62-
group, exists := g.Groups[groupPath]
63-
if !exists {
64-
group = nil
65-
}
66-
return group
61+
return g.Groups[groupPath]
6762
}

mirroring/main.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ func processFilters(filters *utils.MirrorMapping) (map[string]bool, map[string]b
5757
destinationProjectFilters := make(map[string]bool)
5858
destinationGroupFilters := make(map[string]bool)
5959

60-
// Use a mutex to ensure safe updates to destinationGroupFilters, and a waitgroup to
61-
// iterate over the groups and projects concurrently.
60+
// Initialize concurrency control
6261
var mu sync.Mutex
6362
var wg sync.WaitGroup
6463
wg.Add(2)
@@ -69,7 +68,7 @@ func processFilters(filters *utils.MirrorMapping) (map[string]bool, map[string]b
6968
for group, copyOptions := range filters.Groups {
7069
sourceGroupFilters[group] = true
7170
mu.Lock()
72-
destinationGroupFilters[copyOptions.DestinationURL] = true
71+
destinationGroupFilters[copyOptions.DestinationPath] = true
7372
mu.Unlock()
7473
}
7574
}()
@@ -79,10 +78,14 @@ func processFilters(filters *utils.MirrorMapping) (map[string]bool, map[string]b
7978
defer wg.Done()
8079
for project, copyOptions := range filters.Projects {
8180
sourceProjectFilters[project] = true
82-
destinationProjectFilters[copyOptions.DestinationURL] = true
83-
mu.Lock()
84-
destinationGroupFilters[filepath.Dir(copyOptions.DestinationURL)] = true
85-
mu.Unlock()
81+
destinationProjectFilters[copyOptions.DestinationPath] = true
82+
destinationGroupPath := filepath.Dir(copyOptions.DestinationPath)
83+
if destinationGroupPath != "" && destinationGroupPath != "." && destinationGroupPath != "/" {
84+
mu.Lock()
85+
destinationGroupFilters[destinationGroupPath] = true
86+
mu.Unlock()
87+
}
88+
8689
}
8790
}()
8891

mirroring/post.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ func createGroups(sourceGitlab *GitlabInstance, destinationGitlab *GitlabInstanc
1818
// This ensures that the parent groups are created before their children
1919
destinationGroupPaths := make([]string, 0, len(sourceGitlab.Groups))
2020
for sourceGroupPath, createOptions := range mirrorMapping.Groups {
21-
reversedMirrorMap[createOptions.DestinationURL] = sourceGroupPath
22-
destinationGroupPaths = append(destinationGroupPaths, createOptions.DestinationURL)
21+
reversedMirrorMap[createOptions.DestinationPath] = sourceGroupPath
22+
destinationGroupPaths = append(destinationGroupPaths, createOptions.DestinationPath)
2323
}
2424
sort.Strings(destinationGroupPaths)
2525

@@ -71,7 +71,7 @@ func createProjects(sourceGitlab *GitlabInstance, destinationGitlab *GitlabInsta
7171
// Reverse the mirror mapping to get the source project path for each destination project
7272
reversedMirrorMap := make(map[string]string, len(mirrorMapping.Projects))
7373
for sourceProjectPath, projectOptions := range mirrorMapping.Projects {
74-
reversedMirrorMap[projectOptions.DestinationURL] = sourceProjectPath
74+
reversedMirrorMap[projectOptions.DestinationPath] = sourceProjectPath
7575
}
7676

7777
// Create a wait group to wait for all goroutines to finish
@@ -153,21 +153,21 @@ func (g *GitlabInstance) createProjectFromSource(sourceProject *gitlab.Project,
153153
Topics: &sourceProject.Topics,
154154
}
155155

156-
utils.LogVerbosef("Retrieving project namespace ID for %s", copyOptions.DestinationURL)
157-
parentNamespaceId, err := g.getParentNamespaceID(copyOptions.DestinationURL)
156+
utils.LogVerbosef("Retrieving project namespace ID for %s", copyOptions.DestinationPath)
157+
parentNamespaceId, err := g.getParentNamespaceID(copyOptions.DestinationPath)
158158
if err != nil {
159159
return nil, err
160160
} else if parentNamespaceId >= 0 {
161161
projectCreationArgs.NamespaceID = &parentNamespaceId
162162
}
163163

164-
utils.LogVerbosef("Creating project %s in destination GitLab instance", copyOptions.DestinationURL)
164+
utils.LogVerbosef("Creating project %s in destination GitLab instance", copyOptions.DestinationPath)
165165
destinationProject, _, err := g.Gitlab.Projects.CreateProject(projectCreationArgs)
166166
if err != nil {
167167
return nil, err
168168
}
169169
utils.LogVerbosef("Project %s created successfully", destinationProject.PathWithNamespace)
170-
g.addProject(copyOptions.DestinationURL, destinationProject)
170+
g.addProject(copyOptions.DestinationPath, destinationProject)
171171

172172
return destinationProject, nil
173173
}
@@ -181,7 +181,7 @@ func (g *GitlabInstance) createGroupFromSource(sourceGroup *gitlab.Group, copyOp
181181
DefaultBranch: &sourceGroup.DefaultBranch,
182182
}
183183

184-
parentGroupID, err := g.getParentNamespaceID(copyOptions.DestinationURL)
184+
parentGroupID, err := g.getParentNamespaceID(copyOptions.DestinationPath)
185185
if err != nil {
186186
return nil, err
187187
} else if parentGroupID >= 0 {
@@ -190,7 +190,7 @@ func (g *GitlabInstance) createGroupFromSource(sourceGroup *gitlab.Group, copyOp
190190

191191
destinationGroup, _, err := g.Gitlab.Groups.CreateGroup(groupCreationArgs)
192192
if err == nil {
193-
g.addGroup(copyOptions.DestinationURL, destinationGroup)
193+
g.addGroup(copyOptions.DestinationPath, destinationGroup)
194194
}
195195

196196
return destinationGroup, err

utils/types.go

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"bytes"
88
"context"
99
"encoding/json"
10+
"errors"
1011
"fmt"
1112
"net/http"
1213
"os"
@@ -20,9 +21,9 @@ import (
2021
// - ci_cd_catalog: whether to add the project to the CI/CD catalog
2122
// - issues: whether to mirror the issues
2223
type ProjectMirroringOptions struct {
23-
DestinationURL string `json:"destination_url"`
24-
CI_CD_Catalog bool `json:"ci_cd_catalog"`
25-
Issues bool `json:"issues"`
24+
DestinationPath string `json:"destination_path"`
25+
CI_CD_Catalog bool `json:"ci_cd_catalog"`
26+
Issues bool `json:"issues"`
2627
}
2728

2829
// GroupMirrorOptions defines how the group should be mirrored
@@ -31,9 +32,9 @@ type ProjectMirroringOptions struct {
3132
// - ci_cd_catalog: whether to add the group to the CI/CD catalog
3233
// - issues: whether to mirror the issues
3334
type GroupMirroringOptions struct {
34-
DestinationURL string `json:"destination_url"`
35-
CI_CD_Catalog bool `json:"ci_cd_catalog"`
36-
Issues bool `json:"issues"`
35+
DestinationPath string `json:"destination_path"`
36+
CI_CD_Catalog bool `json:"ci_cd_catalog"`
37+
Issues bool `json:"issues"`
3738
}
3839

3940
// MirrorMapping defines the mapping of projects and groups
@@ -92,33 +93,41 @@ func OpenMirrorMapping(path string) (*MirrorMapping, error) {
9293
}
9394

9495
func (m *MirrorMapping) check() error {
95-
errors := make([]string, 0)
96+
errChan := make(chan error, 3*(len(m.Projects)+len(m.Groups)+1))
9697
// Check if the mapping is valid
9798
if len(m.Projects) == 0 && len(m.Groups) == 0 {
98-
errors = append(errors, "no projects or groups defined in the mapping")
99+
errChan <- errors.New("no projects or groups defined in the mapping")
99100
}
100101

101102
// Check if the projects are valid
102103
for project, options := range m.Projects {
103-
if project == "" || options.DestinationURL == "" {
104-
errors = append(errors, fmt.Sprintf(" - invalid project mapping: %s", project))
104+
if project == "" || options.DestinationPath == "" {
105+
errChan <- fmt.Errorf("invalid (empty) string in project mapping: %s", project)
106+
}
107+
if strings.HasPrefix(project, "/") || strings.HasSuffix(project, "/") {
108+
errChan <- fmt.Errorf("invalid project mapping (must not start or end with /): %s", project)
109+
}
110+
if strings.HasPrefix(options.DestinationPath, "/") || strings.HasSuffix(options.DestinationPath, "/") {
111+
errChan <- fmt.Errorf("invalid destination path (must not start or end with /): %s", options.DestinationPath)
112+
} else if strings.Count(options.DestinationPath, "/") < 1 {
113+
errChan <- fmt.Errorf("invalid project destination path (must be in a namespace): %s", options.DestinationPath)
105114
}
106115
}
107116

108117
// Check if the groups are valid
109118
for group, options := range m.Groups {
110-
if group == "" || options.DestinationURL == "" {
111-
errors = append(errors, fmt.Sprintf(" - invalid group mapping: %s", group))
119+
if group == "" || options.DestinationPath == "" {
120+
errChan <- fmt.Errorf("invalid (empty) string in group mapping: %s", group)
121+
}
122+
if strings.HasPrefix(group, "/") || strings.HasSuffix(group, "/") {
123+
errChan <- fmt.Errorf("invalid group mapping (must not start or end with /): %s", group)
124+
}
125+
if strings.HasPrefix(options.DestinationPath, "/") || strings.HasSuffix(options.DestinationPath, "/") {
126+
errChan <- fmt.Errorf("invalid destination path (must not start or end with /): %s", options.DestinationPath)
112127
}
113128
}
114-
115-
// Aggregate errors
116-
var err error = nil
117-
if len(errors) > 0 {
118-
err = fmt.Errorf("invalid mapping: %s", errors)
119-
}
120-
121-
return err
129+
close(errChan)
130+
return MergeErrors(errChan, 2)
122131
}
123132

124133
// GraphQLClient is a client for sending GraphQL requests to GitLab

0 commit comments

Comments
 (0)