fix: разрешить формат owner/repo в имени репозитория (E3 был слишком строг, слэш ≠ эскейп)
All checks were successful
CI / test (push) Successful in 50s
CI / build-and-package (amd64, linux) (push) Successful in 40s
CI / build-and-package (amd64, windows) (push) Successful in 45s

This commit is contained in:
Hermes
2026-08-16 23:00:56 +05:00
parent 4044c0866f
commit 35d9a74ef1
2 changed files with 20 additions and 3 deletions

View File

@@ -370,6 +370,15 @@ func (w *Worker) clone(ctx context.Context, repo string) error {
url := buildCloneURL(base, repo)
dst := filepath.Join(w.Worktree, repo)
// Для формата "owner/repo" git clone не создаёт промежуточный каталог {worktree}/owner
// до самого репозитория — поэтому создаём родителя явно. Worktree в целом гарантирован
// app.New, но вложенные сегменты owner здесь обязательны.
if parent := filepath.Dir(dst); parent != "." && parent != w.Worktree {
if err := os.MkdirAll(parent, 0o755); err != nil {
return fmt.Errorf("%w: создать %s: %v", ErrClone, parent, err)
}
}
args := []string{"clone"}
if w.GitToken != "" {
// https-базовый URL: кладём токен внутрь URL (для приватных репозиториев).
@@ -391,12 +400,20 @@ func buildCloneURL(base, repo string) string {
}
// validateRepoName отклоняет имена с пути-эскейпом (E3).
// Допускается формат "owner/repo" (один слэш) — клон ляжет в {worktree}/owner/repo,
// промежуточный каталог создаёт clone(). Путь с сегментами "." , ".." , пустыми или
// абсолютный — ошибка.
func validateRepoName(repo string) error {
if repo == "" {
return fmt.Errorf("%w: пустое имя", ErrRepoPathHint)
}
if strings.Contains(repo, "/") || strings.Contains(repo, "..") {
if filepath.IsAbs(repo) {
return fmt.Errorf("%w: %q", ErrRepoPathHint, repo)
}
for _, seg := range strings.Split(repo, "/") {
if seg == "" || seg == "." || seg == ".." {
return fmt.Errorf("%w: %q", ErrRepoPathHint, repo)
}
}
return nil
}