diff --git a/cmd/review-bot/main.go b/cmd/review-bot/main.go index 4db81b4..efeb3dd 100644 --- a/cmd/review-bot/main.go +++ b/cmd/review-bot/main.go @@ -168,8 +168,12 @@ func main() { os.Exit(1) } + // Detect VCS type and initialize the appropriate client. + vcsType := detectVCSType() + slog.Info("detected VCS type", "vcs", vcsType) + // Initialize clients - giteaClient := gitea.NewClient(*vcsURL, *reviewerToken) + giteaClient := newVCSClient(vcsType, *vcsURL, *reviewerToken) llmClient := llm.NewClient(*llmBaseURL, *llmAPIKey, *llmModel) if *llmTemp < 0 || *llmTemp > 2 { slog.Error("invalid LLM temperature", "temperature", *llmTemp, "range", "0-2") @@ -207,7 +211,7 @@ func main() { var persona *review.Persona if *personaName != "" { // Try loading from repo first, then fall back to built-in - repoPersonas, err := review.LoadRepoPersonas(ctx, newGiteaClientAdapter(giteaClient), owner, repoName) + repoPersonas, err := review.LoadRepoPersonas(ctx, buildRepoPersonaClient(giteaClient), owner, repoName) if err != nil { slog.Warn("could not load repo personas", "repo", owner+"/"+repoName, "error", err) // Continue with built-in personas only. @@ -527,7 +531,7 @@ func main() { } // fetchFileContext fetches the full content of modified files from the PR branch. -func fetchFileContext(ctx context.Context, client *gitea.Client, owner, repo, ref string, files []gitea.ChangedFile) string { +func fetchFileContext(ctx context.Context, client vcsClient, owner, repo, ref string, files []gitea.ChangedFile) string { var sb strings.Builder for _, f := range files { if ctx.Err() != nil { @@ -554,7 +558,7 @@ func fetchFileContext(ctx context.Context, client *gitea.Client, owner, repo, re // patternsFiles is comma-separated list of file paths or directories. // If a path ends with / or is a directory, all files within it are fetched recursively. // If patternsFiles is empty, all files from the repo root are fetched. -func fetchPatterns(ctx context.Context, client *gitea.Client, patternsRepo, patternsFiles string) string { +func fetchPatterns(ctx context.Context, client vcsClient, patternsRepo, patternsFiles string) string { var sb strings.Builder repos := strings.Split(patternsRepo, ",") @@ -851,31 +855,3 @@ func shouldSkipStaleReview(evaluatedSHA, currentSHA string) bool { return evaluatedSHA != currentSHA } -// giteaClientAdapter adapts gitea.Client to review.GiteaClient interface. -type giteaClientAdapter struct { - client *gitea.Client -} - -func newGiteaClientAdapter(c *gitea.Client) *giteaClientAdapter { - return &giteaClientAdapter{client: c} -} - -func (a *giteaClientAdapter) ListContents(ctx context.Context, owner, repo, path string) ([]review.ContentEntry, error) { - entries, err := a.client.ListContents(ctx, owner, repo, path) - if err != nil { - return nil, err - } - result := make([]review.ContentEntry, len(entries)) - for i, e := range entries { - result[i] = review.ContentEntry{ - Name: e.Name, - Path: e.Path, - Type: e.Type, - } - } - return result, nil -} - -func (a *giteaClientAdapter) GetFileContent(ctx context.Context, owner, repo, filepath string) (string, error) { - return a.client.GetFileContent(ctx, owner, repo, filepath) -}