Documentation
¶
Overview ¶
Package gitwork wraps the git-work CLI for worktree management.
This package provides a Go client for the git-work CLI tool, enabling programmatic management of git worktrees. It handles workspace discovery, worktree creation/removal, and parsing of git-work's JSON output.
git-work CLI Requirements ¶
This package requires git-work to be installed and available in PATH. The git-work CLI must support:
- list --format=json: Output worktree information as JSON to stderr
- checkout -b <branch>: Create a new worktree for the branch (path to stdout)
- rm --yes <branch>: Remove a worktree without confirmation
JSON Format ¶
The git-work list --format=json command outputs JSON to stderr:
{
"data": {
"worktrees": [
{"dir": "main", "branch": "main", "current": false}
]
},
"messages": [
{"level": "info", "text": " main main\n"}
]
}
The "dir" field contains the directory name (not the full path). This package constructs the full path using filepath.Join(repoDir, dir). If git-work is updated to return absolute paths, the code handles that gracefully.
Workspace Discovery ¶
A Substrate workspace is a directory containing a .substrate-workspace file (YAML with ULID, name, timestamp). Workspaces contain git-work repositories, identified by the presence of a .bare/ subdirectory.
Example Usage ¶
client := gitwork.NewClient("")
// List worktrees
worktrees, err := client.List(ctx, repoDir)
if err != nil {
// handle error
}
// Create a new worktree
path, err := client.Checkout(ctx, repoDir, "feature-branch")
if err != nil {
// handle error
}
// Remove a worktree
err = client.Remove(ctx, repoDir, "feature-branch")
if err != nil {
// handle error
}
Index ¶
- Constants
- Variables
- func DiscoverPlainRepos(workspaceDir string) ([]string, error)
- func DiscoverRepos(workspaceDir string) ([]string, error)
- func IsGitWorkRepo(dir string) bool
- func IsNotInWorkspace(err error) bool
- func IsPlainGitRepo(dir string) bool
- func IsWorkspaceExists(err error) bool
- func ValidateWorkspaceID(id string) error
- func WriteWorkspaceFile(dir string, ws *WorkspaceFile) error
- type Client
- func (c *Client) CheckInstalled() error
- func (c *Client) Checkout(ctx context.Context, repoDir, branch string) (string, error)
- func (c *Client) Clone(ctx context.Context, parentDir, remoteURL string) (string, error)
- func (c *Client) GetMainWorktree(ctx context.Context, repoDir string) (string, error)
- func (c *Client) Init(ctx context.Context, repoDir string) error
- func (c *Client) List(ctx context.Context, repoDir string) ([]Worktree, error)
- func (c *Client) PullMainWorktree(ctx context.Context, repoDir string) (string, error)
- func (c *Client) Remove(ctx context.Context, repoDir, branch string) error
- func (c *Client) Sync(ctx context.Context, repoDir string) error
- type PullResult
- type WorkspaceFile
- type WorkspaceScan
- type Worktree
Constants ¶
const (
// WorkspaceFileName is the name of the workspace marker file.
WorkspaceFileName = ".substrate-workspace"
)
Variables ¶
var ( // ErrNotInWorkspace is returned when no workspace file is found. ErrNotInWorkspace = errors.New("not in a substrate workspace") // ErrWorkspaceExists is returned when trying to initialize an existing workspace. ErrWorkspaceExists = errors.New("workspace already exists") )
Functions ¶
func DiscoverPlainRepos ¶
DiscoverPlainRepos scans the workspace directory for plain git repositories. A plain git repository has a .git entry but no .bare/ subdirectory.
func DiscoverRepos ¶
DiscoverRepos scans the workspace directory for git-work repositories. A git-work repository is identified by the presence of a .bare/ subdirectory.
func IsGitWorkRepo ¶
IsGitWorkRepo checks if the given directory is a git-work repository by looking for a .bare subdirectory.
func IsNotInWorkspace ¶
IsNotInWorkspace returns true if err is ErrNotInWorkspace.
func IsPlainGitRepo ¶
IsPlainGitRepo checks if the given directory is a plain git repository. Plain git repositories have a .git entry and do not yet use the git-work .bare layout.
func IsWorkspaceExists ¶
IsWorkspaceExists returns true if err is ErrWorkspaceExists.
func ValidateWorkspaceID ¶
ValidateWorkspaceID checks if the given string is a valid ULID.
func WriteWorkspaceFile ¶
func WriteWorkspaceFile(dir string, ws *WorkspaceFile) error
WriteWorkspaceFile writes the workspace file to the given directory.
Types ¶
type Client ¶
type Client struct {
// BinPath is the path to the git-work binary.
// If empty, "git-work" is looked up in PATH.
BinPath string
}
Client wraps the git-work CLI for worktree management.
func (*Client) CheckInstalled ¶
CheckInstalled verifies that git-work is available in PATH or at BinPath.
func (*Client) Checkout ¶
Checkout creates a new worktree for the given branch and returns its path. The branch is created from the current HEAD if it doesn't exist. The worktree is created in a subdirectory named after the branch.
func (*Client) Clone ¶
Clone clones a remote repository into the workspace using git-work clone. It runs git-work clone <remoteURL> with cmd.Dir = parentDir. git-work clone creates <parentDir>/<repo-name>/.bare/ layout and a worktree for HEAD. It parses stdout for the directory path and validates the path is under parentDir. Returns the absolute path to the created repository root.
func (*Client) GetMainWorktree ¶
GetMainWorktree returns the path to the main worktree for a repository.
func (*Client) List ¶
Context cancellation is honored: if ctx is cancelled, the command will be terminated and an error returned. Partial JSON output on cancellation is handled by parseListJSON which returns an empty slice for empty input.
func (*Client) PullMainWorktree ¶
PullMainWorktree runs git pull --ff-only in the main worktree of the given repo. It returns the output and any error. Unlike other methods, this does not wrap the error - the caller should handle it appropriately (as a warning, not a failure).
type PullResult ¶
PullResult represents the result of pulling a single repo's main worktree.
type WorkspaceFile ¶
type WorkspaceFile struct {
// ID is a ULID identifying the workspace.
ID string `yaml:"id"`
// Name is a human-readable workspace name.
Name string `yaml:"name"`
// CreatedAt is the timestamp when the workspace was created.
CreatedAt time.Time `yaml:"created_at"`
}
WorkspaceFile represents the content of .substrate-workspace file.
func FindWorkspace ¶
func FindWorkspace(startDir string) (string, *WorkspaceFile, error)
FindWorkspace searches for a workspace file starting from the given directory and walking up the directory tree. Returns the workspace directory and file, or ErrNotInWorkspace if not found.
func InitWorkspace ¶
func InitWorkspace(dir, name string) (*WorkspaceFile, error)
func ReadWorkspaceFile ¶
func ReadWorkspaceFile(dir string) (*WorkspaceFile, error)
ReadWorkspaceFile reads the workspace file from the given directory. Returns ErrNotInWorkspace if no workspace file exists.
func ResolveWorkspacePath ¶
func ResolveWorkspacePath(storedPath string) (string, *WorkspaceFile, error)
ResolveWorkspacePath attempts to read the workspace file from the given path and returns the absolute path. This is used for path reconciliation when a workspace directory may have been moved. Returns the absolute path, workspace file, and error if the workspace cannot be found.
type WorkspaceScan ¶
WorkspaceScan classifies direct child directories in a workspace.
func ScanWorkspace ¶
func ScanWorkspace(workspaceDir string) (WorkspaceScan, error)
ScanWorkspace scans the workspace directory for managed and plain git repositories.