diff --git a/config/assignment.go b/config/assignment.go index 176a1ff..4e17c5b 100644 --- a/config/assignment.go +++ b/config/assignment.go @@ -9,19 +9,6 @@ import ( "github.com/spf13/viper" ) -func (ac AccessLevel) String() string { - if ac == 10 { - return "guest" - } - if ac == 20 { - return "reporter" - } - if ac == 30 { - return "developer" - } - return "maintainer" -} - func GetAssignmentConfig(course, assignment string, onlyForStudentsOrGroups ...string) *AssignmentConfig { if !viper.IsSet(course) { log.Fatal(). @@ -56,21 +43,27 @@ func GetAssignmentConfig(course, assignment string, onlyForStudentsOrGroups ...s Course: course, Name: assignment, UseCoursenameAsPrefix: viper.GetBool(course + ".useCoursenameAsPrefix"), - Path: path, - URL: url, - Per: per, - Description: description(assignmentKey), - ContainerRegistry: containerRegistry, - AccessLevel: accessLevel(assignmentKey), - MergeRequest: mergeRequest(assignmentKey), - Branches: branchRules, - Issues: issues(assignmentKey), - Students: students(per, course, assignment, onlyForStudentsOrGroups...), - Groups: groups(per, course, assignment, onlyForStudentsOrGroups...), - Startercode: starter, - Clone: clone(assignmentKey, defaultCloneBranch), - Release: release, - Seeder: seeder(assignmentKey), + UseEmailDomainAsSuffix: func() bool { + if viper.IsSet(course + ".useEmailDomainAsSuffix") { + return viper.GetBool(course + ".useEmailDomainAsSuffix") + } + return true // default + }(), + Path: path, + URL: url, + Per: per, + Description: description(assignmentKey), + ContainerRegistry: containerRegistry, + AccessLevel: accessLevel(assignmentKey), + MergeRequest: mergeRequest(assignmentKey), + Branches: branchRules, + Issues: issues(assignmentKey), + Students: students(per, course, assignment, onlyForStudentsOrGroups...), + Groups: groups(per, course, assignment, onlyForStudentsOrGroups...), + Startercode: starter, + Clone: clone(assignmentKey, defaultCloneBranch), + Release: release, + Seeder: seeder(assignmentKey), } return assignmentConfig @@ -80,6 +73,12 @@ func GetAssignmentConfig(course, assignment string, onlyForStudentsOrGroups ...s // This is incompatible to the filesystem and gitlab so replacing the values is necessary. func (cfg *AssignmentConfig) RepoSuffix(student *Student) string { if student.Email != nil { + // If explicitly set to false, always use part before @ + if viper.IsSet(cfg.Course+".useEmailDomainAsSuffix") && !cfg.UseEmailDomainAsSuffix { + parts := strings.SplitN(*student.Email, "@", 2) + return parts[0] + } + // Default: use _at_ replacement return strings.ReplaceAll(*student.Email, "@", "_at_") } if student.Id != nil { @@ -88,7 +87,6 @@ func (cfg *AssignmentConfig) RepoSuffix(student *Student) string { if student.Username != nil { return *student.Username } - return "" } diff --git a/config/assignment_test.go b/config/assignment_test.go index e388b02..ae55a37 100644 --- a/config/assignment_test.go +++ b/config/assignment_test.go @@ -47,10 +47,25 @@ func TestRepoNamingHelpers(t *testing.T) { mail := "a@b.example" user := "alice" + // Default (field not set, should use suffix) cfg := &AssignmentConfig{Course: "mpd", Name: "blatt01", UseCoursenameAsPrefix: true} + viper.Reset() + if got := cfg.RepoSuffix(&Student{Email: &mail}); got != "a_at_b.example" { + t.Fatalf("RepoSuffix(email, default) = %q", got) + } + // Explicitly set to true + viper.Set("mpd.useEmailDomainAsSuffix", true) + cfg.UseEmailDomainAsSuffix = true if got := cfg.RepoSuffix(&Student{Email: &mail}); got != "a_at_b.example" { - t.Fatalf("RepoSuffix(email) = %q", got) + t.Fatalf("RepoSuffix(email, true) = %q", got) + } + + // Explicitly set to false + viper.Set("mpd.useEmailDomainAsSuffix", false) + cfg.UseEmailDomainAsSuffix = false + if got := cfg.RepoSuffix(&Student{Email: &mail}); got != "a" { + t.Fatalf("RepoSuffix(email, false) = %q", got) } if got := cfg.RepoSuffix(&Student{Id: &id}); got != "123" { t.Fatalf("RepoSuffix(id) = %q", got) diff --git a/config/show.go b/config/show.go index 7db0c91..fcbb747 100644 --- a/config/show.go +++ b/config/show.go @@ -101,6 +101,7 @@ func (cfg *AssignmentConfig) Show() { fieldCandidate(0, "Course"), fieldCandidate(0, "Assignment"), fieldCandidate(0, "Coursename-Prefix"), + fieldCandidate(0, "EmailDomain-Suffix"), fieldCandidate(0, "Per"), fieldCandidate(0, "Base-URL"), fieldCandidate(0, "Description"), @@ -155,6 +156,7 @@ func (cfg *AssignmentConfig) Show() { writeTopField("Course", cfg.Course) writeTopField("Assignment", cfg.Name) writeTopField("Coursename-Prefix", cfg.UseCoursenameAsPrefix) + writeTopField("EmailDomain-Suffix", cfg.UseEmailDomainAsSuffix) writeTopField("Per", cfg.Per) writeTopField("Base-URL", cfg.URL) writeTopField("Description", cfg.Description) diff --git a/config/types.go b/config/types.go index ffb3621..275bf3e 100644 --- a/config/types.go +++ b/config/types.go @@ -2,6 +2,21 @@ package config import "github.com/ProtonMail/go-crypto/openpgp" +func (ac AccessLevel) String() string { + switch ac { + case 10: + return "guest" + case 20: + return "reporter" + case 30: + return "developer" + case 40: + return "maintainer" + default: + return "maintainer" + } +} + type Student struct { Id *int Username *string @@ -10,24 +25,25 @@ type Student struct { } type AssignmentConfig struct { - Course string - Name string - UseCoursenameAsPrefix bool - Path string - URL string - Per Per - Description string - ContainerRegistry bool - AccessLevel AccessLevel - MergeRequest *MergeRequest - Branches []BranchRule - Issues *IssueReplication - Students []*Student - Groups []*Group - Startercode *Startercode - Clone *Clone - Release *Release - Seeder *Seeder + Course string + Name string + UseCoursenameAsPrefix bool + UseEmailDomainAsSuffix bool + Path string + URL string + Per Per + Description string + ContainerRegistry bool + AccessLevel AccessLevel + MergeRequest *MergeRequest + Branches []BranchRule + Issues *IssueReplication + Students []*Student + Groups []*Group + Startercode *Startercode + Clone *Clone + Release *Release + Seeder *Seeder } type Per string diff --git a/docs/configuration.md b/docs/configuration.md index ab6918b..7e95355 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -83,6 +83,7 @@ mpd: | `coursepath` | GitLab subgroup path for course | — | Required | | `semesterpath` | Additional grouping level | — | Optional | | `useCoursenameAsPrefix` | Prepend course name to project names | `false` | Example: `mpd-blatt01` | +| `useEmailDomainAsSuffix` | Use full email (with `_at_...`) as repo suffix | `true` | If `false`, only the part before `@` is used (e.g. `alice` instead of `alice_at_example.org`). | | `students` | List of course-wide students | — | Can be overridden per assignment | | `groups` | Dict of group → student lists | — | For `per: group` assignments | @@ -94,7 +95,9 @@ Students and groups can be specified by: - **Username**: `alice` - **User ID**: `12345` -You can mix formats. If using emails, the `@` is replaced with `_at_` in project names (filesystem compatibility). + +You can mix formats. By default, if using emails, the `@` is replaced with `_at_` in project names (filesystem compatibility), e.g. `mpd-blatt01-alice_at_example.org`. +If you set `useEmailDomainAsSuffix: false`, only the part before the `@` is used, e.g. `mpd-blatt01-alice`. ### Student/Group filtering