package bitbucket import ( "context" "fmt" "io" "net/http" "strings" "git.schreifuchs.ch/schreifuchs/pierre-bot/internal/gitadapters/baseadapter" ) type BitbucketAdapter struct { baseadapter.Rest } func NewBitbucket(baseURL string, bearerToken string) *BitbucketAdapter { baseURL, _ = strings.CutSuffix(baseURL, "/") baseURL += "/rest/api/1.0" return &BitbucketAdapter{ Rest: baseadapter.NewRest(baseURL, bearerToken), } } // GetFileContent returns the raw file content at the given ref (commit SHA) or HEAD if ref is empty. func (b *BitbucketAdapter) GetFileContent(ctx context.Context, projectKey, repositorySlug, path, ref string) (string, error) { // Use the Rest helper to build the base URL, then add the "at" query param if needed. r, err := b.CreateRequest(ctx, http.MethodGet, nil, "/projects/", projectKey, "repos", repositorySlug, "raw", path) if err != nil { return "", err } // Ensure raw file retrieval r.Header.Set("Accept", "application/octet-stream") if ref != "" { q := r.URL.Query() q.Set("at", ref) r.URL.RawQuery = q.Encode() } resp, err := http.DefaultClient.Do(r) if err != nil { return "", err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { sb := &strings.Builder{} io.Copy(sb, resp.Body) return "", fmt.Errorf("error fetching file %s status %d, body %s", path, resp.StatusCode, sb.String()) } content, err := io.ReadAll(resp.Body) if err != nil { return "", err } return string(content), nil } // GetPRHeadSHA fetches the PR and returns the SHA of the source (to) branch. func (b *BitbucketAdapter) GetPRHeadSHA(ctx context.Context, projectKey, repositorySlug string, pullRequestID int) (string, error) { pr, err := b.GetPR(ctx, projectKey, repositorySlug, pullRequestID) if err != nil { return "", err } return pr.ToRef.LatestCommit, nil }