diff --git a/packages/sandbox/daemon-go/internal/config/validate.go b/packages/sandbox/daemon-go/internal/config/validate.go index 5163dccae9..9220ed362d 100644 --- a/packages/sandbox/daemon-go/internal/config/validate.go +++ b/packages/sandbox/daemon-go/internal/config/validate.go @@ -81,6 +81,7 @@ func validateGit(git *GitConfig) string { return fmt.Sprintf("git.repository.branch invalid: %s", b) } } + seenRepoNames := make(map[string]bool, len(git.Repositories)) for i, repo := range git.Repositories { if repo.CloneUrl == nil || *repo.CloneUrl == "" { return fmt.Sprintf("git.repositories[%d].cloneUrl is required", i) @@ -89,6 +90,13 @@ func validateGit(git *GitConfig) string { if repo.RepoName == nil || !repoNameRe.MatchString(*repo.RepoName) { return fmt.Sprintf("git.repositories[%d].repoName invalid", i) } + // Two repos resolving to the same directory would clone concurrently + // into it (cloneSecondaryRepos fans out before any dir exists to skip + // on), corrupting both checkouts. + if seenRepoNames[*repo.RepoName] { + return fmt.Sprintf("git.repositories[%d].repoName duplicates another entry: %s", i, *repo.RepoName) + } + seenRepoNames[*repo.RepoName] = true if repo.Branch != nil { b := *repo.Branch if !IsSyntheticBranch(b) && (!branchRe.MatchString(b) || strings.HasPrefix(b, "-")) { diff --git a/packages/sandbox/daemon-go/internal/config/validate_test.go b/packages/sandbox/daemon-go/internal/config/validate_test.go index 72c05334e8..7c669b5a35 100644 --- a/packages/sandbox/daemon-go/internal/config/validate_test.go +++ b/packages/sandbox/daemon-go/internal/config/validate_test.go @@ -37,3 +37,16 @@ func TestValidateApplicationRejectsEscapingPmPath(t *testing.T) { t.Fatal("validateApplication accepted a packageManager.path that escapes the repo root") } } + +func TestValidateGitRejectsDuplicateSecondaryRepoNames(t *testing.T) { + git := &GitConfig{ + Repository: &GitRepository{CloneUrl: Str("https://example.com/primary.git")}, + Repositories: []GitRepository{ + {CloneUrl: Str("https://example.com/a.git"), RepoName: Str("storefront")}, + {CloneUrl: Str("https://example.com/b.git"), RepoName: Str("storefront")}, + }, + } + if reason := validateGit(git); reason == "" { + t.Fatal("validateGit accepted two secondary repositories with the same repoName, which resolve to the same clone directory") + } +}