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
2223type 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
3334type 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
9495func (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