diff --git a/contents.go b/contents.go index 01d1ea2..ac08739 100644 --- a/contents.go +++ b/contents.go @@ -2,6 +2,7 @@ package forge import ( "context" + "iter" "net/url" "dappco.re/go/core/forge/types" @@ -44,6 +45,23 @@ func (s *ContentService) ListContents(ctx context.Context, owner, repo, ref stri return out, nil } +// IterContents returns an iterator over the entries in a repository directory. +// If ref is non-empty, the listing is resolved against that branch, tag, or commit. +func (s *ContentService) IterContents(ctx context.Context, owner, repo, ref string) iter.Seq2[types.ContentsResponse, error] { + return func(yield func(types.ContentsResponse, error) bool) { + items, err := s.ListContents(ctx, owner, repo, ref) + if err != nil { + yield(*new(types.ContentsResponse), err) + return + } + for _, item := range items { + if !yield(item, nil) { + return + } + } + } +} + // GetFile returns metadata and content for a file in a repository. func (s *ContentService) GetFile(ctx context.Context, owner, repo, filepath string) (*types.ContentsResponse, error) { path := ResolvePath("/api/v1/repos/{owner}/{repo}/contents/{filepath}", pathParams("owner", owner, "repo", repo, "filepath", filepath)) diff --git a/contents_test.go b/contents_test.go index 2a7966c..abc0b6d 100644 --- a/contents_test.go +++ b/contents_test.go @@ -41,6 +41,38 @@ func TestContentService_ListContents_Good(t *testing.T) { } } +func TestContentService_IterContents_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/repos/core/go-forge/contents" { + t.Errorf("wrong path: %s", r.URL.Path) + } + w.Header().Set("X-Total-Count", "2") + json.NewEncoder(w).Encode([]types.ContentsResponse{ + {Name: "README.md", Path: "README.md", Type: "file"}, + {Name: "docs", Path: "docs", Type: "dir"}, + }) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + var got []string + for item, err := range f.Contents.IterContents(context.Background(), "core", "go-forge", "") { + if err != nil { + t.Fatal(err) + } + got = append(got, item.Name) + } + if len(got) != 2 { + t.Fatalf("got %d items, want 2", len(got)) + } + if got[0] != "README.md" || got[1] != "docs" { + t.Fatalf("unexpected items: %+v", got) + } +} + func TestContentService_GetFile_Good(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { diff --git a/webhooks.go b/webhooks.go index bdd0818..0824aba 100644 --- a/webhooks.go +++ b/webhooks.go @@ -59,6 +59,12 @@ func (s *WebhookService) ListGitHooks(ctx context.Context, owner, repo string) ( return ListAll[types.GitHook](ctx, s.client, path, nil) } +// IterGitHooks returns an iterator over all Git hooks for a repository. +func (s *WebhookService) IterGitHooks(ctx context.Context, owner, repo string) iter.Seq2[types.GitHook, error] { + path := ResolvePath("/api/v1/repos/{owner}/{repo}/hooks/git", pathParams("owner", owner, "repo", repo)) + return ListIter[types.GitHook](ctx, s.client, path, nil) +} + // GetGitHook returns a single Git hook for a repository. func (s *WebhookService) GetGitHook(ctx context.Context, owner, repo, id string) (*types.GitHook, error) { path := ResolvePath("/api/v1/repos/{owner}/{repo}/hooks/git/{id}", pathParams("owner", owner, "repo", repo, "id", id)) diff --git a/webhooks_test.go b/webhooks_test.go index 84965d0..68d1ff9 100644 --- a/webhooks_test.go +++ b/webhooks_test.go @@ -155,6 +155,37 @@ func TestWebhookService_ListGitHooks_Good(t *testing.T) { } } +func TestWebhookService_IterGitHooks_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/repos/core/go-forge/hooks/git" { + t.Errorf("wrong path: %s", r.URL.Path) + } + w.Header().Set("X-Total-Count", "1") + json.NewEncoder(w).Encode([]types.GitHook{ + {Name: "pre-receive", Content: "#!/bin/sh\nexit 0", IsActive: true}, + }) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + var got []string + for hook, err := range f.Webhooks.IterGitHooks(context.Background(), "core", "go-forge") { + if err != nil { + t.Fatal(err) + } + got = append(got, hook.Name) + } + if len(got) != 1 { + t.Fatalf("got %d hooks, want 1", len(got)) + } + if got[0] != "pre-receive" { + t.Errorf("got name=%q, want %q", got[0], "pre-receive") + } +} + func TestWebhookService_GetGitHook_Good(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet {