b30933240b
* fix: sanitize multi-repo worktree dirs and polish task-create chip dropdown Backend: org-prefixed Repository.Name like "owner/repo" was used verbatim as the worktree subdirectory under the task root, nesting one level too deep and breaking agentctl's sibling-based multi-repo detection in scanRepositorySubdirs. Sanitize to a single path-safe segment so all worktrees land as siblings of the task root. Web: the multi-repo chip dropdown built its own option list and dropped the path Badge plus search filtering that the legacy header dropdown shipped. Restore parity (name + path), widen the popover (288 → 360 px), stack name and full path on two lines so neither has to truncate aggressively, hide the Badge for workspace repos without a local clone, and use a path-aware scorer that floors weak fuzzy matches so unrelated paths stop surfacing for short queries. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address PR review feedback - Add ErrInvalidRepoName sentinel and use it in createInTaskDir when RepoName sanitizes to empty, replacing the misleading reuse of ErrTaskDirRequired (Claude/Greptile). - Reuse repoDirHyphenRun in SanitizeForBranch instead of recompiling the regexp per call (CodeRabbit nitpick). - Document the SanitizeRepoDirName collision edge case in the doc comment (Greptile). - Extract scoreRepo to lib/utils/repo-filter.ts and add unit tests pinning the 0.4 fuzzy-match threshold (Claude). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Kandev Agent <agent@kandev.dev> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
30 lines
720 B
Go
30 lines
720 B
Go
package worktree
|
|
|
|
import "testing"
|
|
|
|
func TestSanitizeRepoDirName(t *testing.T) {
|
|
cases := []struct {
|
|
in, want string
|
|
}{
|
|
{"widget-config", "widget-config"},
|
|
{"acme/widget-config", "acme-widget-config"},
|
|
{"acme/widget", "acme-widget"},
|
|
{"owner\\repo", "owner-repo"},
|
|
{"weird:name space", "weird-name-space"},
|
|
{"with..dots", "with..dots"},
|
|
{"trailing/", "trailing"},
|
|
{"/leading", "leading"},
|
|
{"a//b", "a-b"},
|
|
{"-a-b-", "a-b"},
|
|
{".hidden", "hidden"},
|
|
{"!@#$%", ""},
|
|
{"", ""},
|
|
{"under_score.dot-dash", "under_score.dot-dash"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := SanitizeRepoDirName(c.in); got != c.want {
|
|
t.Errorf("SanitizeRepoDirName(%q) = %q, want %q", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|