Skip to content

Getting started

Clone a public repository into memory and read a file out of it — no disk, no credentials, no cleanup.

go get gitlab.com/phpboyscout/go/repo

A first repository

package main

import (
    "fmt"
    "log"

    "github.com/spf13/afero"
    "gitlab.com/phpboyscout/go/repo"
)

func main() {
    r, err := repo.NewRepo(repo.Settings{
        Forge: repo.ForgeGitLab,
        FS:    afero.NewOsFs(),
    })
    if err != nil {
        log.Fatal(err)
    }

    // Clone into RAM, shallow — we only need the tip.
    if _, _, err := r.OpenInMemory(
        "https://gitlab.com/phpboyscout/go/repo.git", "main",
        repo.WithShallowClone(1),
    ); err != nil {
        log.Fatal(err)
    }

    file, err := r.GetFile("go.mod")
    if err != nil {
        log.Fatal(err)
    }

    contents, err := file.Contents()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(contents)
}

Three things to notice, because they are the shape of the whole API:

No forge client anywhere. Forge is a string naming an authentication convention, not a GitHub or GitLab SDK. Cloning a repository does not drag a vendor client into your dependency graph — see why git needs no forge.

No credentials for a public repository. Add a Token for a private one; set Private: true and a missing token becomes a clear error instead of a confusing git failure. See authenticate to a forge.

OpenInMemory binds the repository to r. Later calls — GetFile, AddAll, Commit — need no handle. Call one before opening and you get ErrNoRepository or ErrNoWorktree back; never a panic.

Now write something

The worktree is an afero.Fs, and writes to it are the worktree — no sync step:

fs, err := r.WorkFS()
if err != nil {
    log.Fatal(err)
}

if err := afero.WriteFile(fs, "NOTES.md", []byte("hello\n"), 0o644); err != nil {
    log.Fatal(err)
}

if err := r.AddAll(); err != nil {
    log.Fatal(err)
}

hash, err := r.Commit("docs: add notes", nil)

AddAll honours .gitignore, so build artefacts stay out of the commit. Because the repository is in memory, this commit exists only in your process — nothing to clean up.

Where next