Repository Operations¶
The repo package provides high-level functions for repository operations including forking, branching, committing, and batch file operations.
Listing Repositories¶
List User Repositories¶
import "github.com/grokify/gogithub/repo"
repos, err := repo.ListUserRepos(ctx, gh, "octocat", nil)
for _, r := range repos {
fmt.Printf("%s: %s\n", r.GetFullName(), r.GetDescription())
}
List Organization Repositories¶
Get Single Repository¶
Branch Operations¶
Get Branch SHA¶
Create Branch¶
// First get the SHA of the base branch
sha, err := repo.GetBranchSHA(ctx, gh, "owner", "repo", "main")
if err != nil {
return err
}
// Create new branch from that SHA
err = repo.CreateBranch(ctx, gh, "owner", "repo", "feature-branch", sha)
Delete Branch¶
Get Default Branch¶
defaultBranch, err := repo.GetDefaultBranch(ctx, gh, "owner", "repo")
fmt.Printf("Default branch: %s\n", defaultBranch)
Fork Operations¶
Ensure Fork Exists¶
EnsureFork creates a fork if it doesn't exist, or returns the existing fork:
fork, err := repo.EnsureFork(ctx, gh, "upstream-owner", "upstream-repo")
fmt.Printf("Fork: %s/%s\n", fork.GetOwner().GetLogin(), fork.GetName())
Commit Operations¶
Create Single Commit¶
Create a commit with multiple files using the Git Data API (tree-based):
files := []repo.FileContent{
{Path: "README.md", Content: []byte("# Hello World")},
{Path: "src/main.go", Content: []byte("package main\n\nfunc main() {}")},
}
commit, err := repo.CreateCommit(ctx, gh, "owner", "repo", "feature-branch", "Add initial files", files)
fmt.Printf("Commit SHA: %s\n", commit.GetSHA())
Read Local Files¶
Helper to read files from the local filesystem:
files, err := repo.ReadLocalFiles("path/to/dir", []string{"file1.txt", "file2.txt"})
if err != nil {
return err
}
commit, err := repo.CreateCommit(ctx, gh, "owner", "repo", "branch", "Add files", files)
Batch Operations¶
The Batch type allows atomic multi-file commits with queued operations:
Create a Batch¶
batch, err := repo.NewBatch(ctx, gh, "owner", "repo", "feature-branch")
if err != nil {
return err
}
Queue Operations¶
// Queue file writes
err = batch.Write("README.md", []byte("# Updated README"))
err = batch.Write("docs/guide.md", []byte("# Guide"))
// Queue file deletions
err = batch.Delete("old-file.txt")
Commit All Changes¶
commit, err := batch.Commit(ctx, "Update documentation")
if err != nil {
return err
}
fmt.Printf("Committed: %s\n", commit.GetSHA())
With Custom Author¶
batch, err := repo.NewBatch(ctx, gh, "owner", "repo", "branch",
repo.WithCommitAuthor("Bot", "bot@example.com"),
)
Full Example¶
batch, err := repo.NewBatch(ctx, gh, "owner", "repo", "main")
if err != nil {
return err
}
// Queue multiple operations
batch.Write("config.json", []byte(`{"version": 2}`))
batch.Write("src/app.go", []byte("package main"))
batch.Delete("deprecated.txt")
// Commit atomically
commit, err := batch.Commit(ctx, "Refactor configuration")
if err != nil {
return err
}
fmt.Printf("All changes committed in: %s\n", commit.GetSHA())
Batch Commits Are Single-Use
A Batch can only be committed once. After calling Commit(), create a new Batch for additional changes.
Path Validation¶
The pathutil package (used internally) validates and normalizes file paths:
import "github.com/grokify/gogithub/pathutil"
// Validate path (rejects traversal attempts)
err := pathutil.Validate("../etc/passwd") // Returns error
// Normalize path
normalized := pathutil.Normalize("/foo//bar/./baz") // "foo/bar/baz"
// Join paths safely
path := pathutil.Join("dir", "subdir", "file.txt") // "dir/subdir/file.txt"
Error Types¶
CommitError¶
commit, err := repo.CreateCommit(ctx, gh, owner, repo, branch, msg, files)
if err != nil {
var commitErr *repo.CommitError
if errors.As(err, &commitErr) {
fmt.Printf("Commit failed for %s/%s: %v\n",
commitErr.Owner, commitErr.Repo, commitErr.Err)
}
}
BatchError¶
commit, err := batch.Commit(ctx, message)
if err != nil {
var batchErr *repo.BatchError
if errors.As(err, &batchErr) {
fmt.Printf("Batch commit failed: %s\n", batchErr.Message)
}
}
API Reference¶
See pkg.go.dev/github.com/grokify/gogithub/repo for complete API documentation.