config

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package config loads treehouse's JSON configuration. The file location comes from $TH_CONFIG, defaulting to ~/.th/config.json; a missing file at the default location means built-in defaults apply.

Index

Constants

View Source
const (
	SourceDefault  = "default"
	SourceTopLevel = "top-level"
	SourceLocal    = LocalFileName
)

Source labels for Provenance: the layer an effective value came from.

View Source
const DefaultPrefixSeparator = "/"

DefaultPrefixSeparator joins branch_prefix to the branch name when no config sets prefix_separator.

View Source
const DefaultWorktreeDir = "~/worktrees/{repo}/{branch}"

DefaultWorktreeDir places worktrees when no config sets worktree_dir.

View Source
const EnvVar = "TH_CONFIG"

EnvVar overrides the config file location.

View Source
const LocalFileName = ".thrc"

LocalFileName is the repo-local config file, read from the root of a repository's main worktree only — never from a linked worktree.

View Source
const TrustFileName = "trust.json"

TrustFileName is the approval store for repo-sourced post_create commands. It lives at ~/.th/trust.json regardless of $TH_CONFIG: it is per-user machine state, not configuration, and must not travel with a config file.

Variables

This section is empty.

Functions

func ApprovePostCreate

func ApprovePostCreate(mainPath string, cmds []string) error

ApprovePostCreate records cmds as approved for the repository whose main worktree is at mainPath, replacing any previous approval. The store is written atomically (temp file plus rename) with mode 0600.

func ApprovedPostCreate

func ApprovedPostCreate(mainPath string) ([]string, bool)

ApprovedPostCreate returns the post_create commands the user approved for the repository whose main worktree is at mainPath, and whether an approval record exists at all. It never fails: with no usable record the caller prompts for approval.

func ExpandTilde

func ExpandTilde(p string) (string, error)

func Path

func Path() (path string, explicit bool, err error)

Path returns the config file location and whether it was set explicitly via $TH_CONFIG.

func ResolveDetailed

func ResolveDetailed(mainPath string) (Resolved, Provenance, error)

ResolveDetailed is Resolve, additionally reporting where each effective value came from.

func ResolveGlobal

func ResolveGlobal() (Resolved, Provenance, error)

ResolveGlobal resolves only the repo-independent layers — built-in defaults and the config file's top-level settings — for use outside any repository.

func SanitizeBranch

func SanitizeBranch(branch string) string

SanitizeBranch makes a branch name safe to use as a single path segment.

Types

type File

type File struct {
	Settings
	Repos []RepoConfig `json:"repos,omitempty"`
	// UpdateCheck lets th --version query GitHub for a newer release.
	// Deliberately top-level only — not part of Settings — so a repo's
	// .thrc can never turn on network calls.
	UpdateCheck *bool `json:"update_check,omitempty"`
}

File is the full global-config schema: top-level defaults plus per-repo overrides matched by the main worktree's path.

func Load

func Load() (*File, error)

Load reads the config file. A missing file at the default location is not an error; a missing file at an explicit $TH_CONFIG location is, so a typo'd path fails loudly instead of being silently ignored.

func (*File) ForPath

func (f *File) ForPath(mainPath string) (Settings, string)

ForPath returns the effective settings for the repository whose main worktree is at mainPath: built-in defaults, overlaid with the file's top-level settings, overlaid with the first repos entry whose path matches. The second return is the matching entry's name ("" when unnamed or no entry matches).

func (*File) UpdateCheckEnabled

func (f *File) UpdateCheckEnabled() bool

UpdateCheckEnabled reports whether update_check is set and true.

type LocalConfig

type LocalConfig struct {
	// Name is what {repo} expands to for this repo. It overrides the name
	// of a matching global repos entry. Empty means the entry's name, or
	// the directory basename of the main worktree.
	Name string `json:"name,omitempty"`
	Settings
}

LocalConfig is the .thrc schema: the same settings as a repos entry, for the repository the file lives in. It is parsed with unknown fields rejected, so "repos" and "path" — meaningless in a file that is itself the repo — fail loudly.

type Provenance

type Provenance struct {
	// Fields maps a setting's JSON name to the label of the layer that
	// last set it: SourceTopLevel, "repos[N]", or SourceLocal. Settings
	// no layer set are absent — their values are built-in defaults.
	Fields map[string]string
	// ReposIndex is the index of the repos entry that matched, -1 if none.
	ReposIndex int
	// ReposPath is the matching repos entry's configured path, "" if none.
	ReposPath string
}

Provenance records which layer set each effective value.

func (Provenance) Source

func (p Provenance) Source(field string) string

Source returns the label of the layer that set the field with the given JSON name, SourceDefault when no layer did.

type RepoConfig

type RepoConfig struct {
	// Name is what {repo} expands to in templates for this repo. Empty
	// means the directory basename of the main worktree.
	Name string `json:"name,omitempty"`
	// Path is the filesystem path of the repo's main worktree.
	Path string `json:"path"`
	Settings
}

RepoConfig is one repos entry: settings for the repository whose main worktree lives at Path.

type Resolved

type Resolved struct {
	Settings
	// RepoName is the .thrc name, else the global repos entry's name,
	// else "" (the caller falls back to the directory basename).
	RepoName string
	// LocalFile is the path of the .thrc that was loaded, "" if none.
	LocalFile string
	// PostCreateFromRepo reports that the effective PostCreate came from
	// .thrc rather than the user-owned global config, and so needs
	// approval before it runs.
	PostCreateFromRepo bool
}

Resolved is the effective configuration for one repository, plus where the values came from.

func Resolve

func Resolve(mainPath string) (Resolved, error)

Resolve returns the effective settings for the repository whose main worktree is at mainPath, layering built-in defaults, the global config's top-level settings, its matching repos entry, and finally the repo's own .thrc. Each layer overrides field by field: empty strings fall through, lists and booleans that are set replace the layer below.

type Settings

type Settings struct {
	// WorktreeDir is a path template; {repo} and {branch} are substituted
	// and a leading ~ expands to the home directory.
	WorktreeDir string `json:"worktree_dir,omitempty"`
	// DefaultBase is the ref new branches start from when the branch exists
	// neither locally nor on origin. Empty means the current HEAD.
	DefaultBase string `json:"default_base,omitempty"`
	// BranchPrefix is prepended to branch names that th add creates,
	// joined with PrefixSeparator: "peter" -> "peter/fix-login".
	BranchPrefix string `json:"branch_prefix,omitempty"`
	// PrefixSeparator joins BranchPrefix to the branch name. Empty means
	// DefaultPrefixSeparator.
	PrefixSeparator string `json:"prefix_separator,omitempty"`
	// CopyHooks copies the repo's git hooks into newly created worktrees.
	// Only relevant when core.hooksPath points inside the worktree (e.g.
	// husky's .husky); plain .git/hooks is already shared by all worktrees.
	// A pointer so a per-repo false can override a global true.
	CopyHooks *bool `json:"copy_hooks,omitempty"`
	// CopyFiles are paths or globs, relative to the main worktree, of
	// untracked files (e.g. ".env") to copy into newly created worktrees.
	// A repo entry's list replaces the global one; [] disables copying.
	CopyFiles []string `json:"copy_files,omitempty"`
	// VSCodeOpen opens the worktree in VS Code after th add creates it.
	VSCodeOpen *bool `json:"vscode_open,omitempty"`
	// VSCodeWorkspaceFile writes a .code-workspace file into each new
	// worktree, named "<vscode_workspace_prefix><branch>.code-workspace".
	VSCodeWorkspaceFile *bool `json:"vscode_workspace_file,omitempty"`
	// VSCodeWorkspacePrefix is prepended to the workspace file's name.
	VSCodeWorkspacePrefix string `json:"vscode_workspace_prefix,omitempty"`
	// VSCodeWindowTitle is written verbatim as the workspace file's
	// settings["window.title"], so VS Code title variables like
	// ${activeEditorShort} pass through. Empty means the repo name.
	VSCodeWindowTitle string `json:"vscode_window_title,omitempty"`
	// WorkspacePaths are extra folders added to generated .code-workspace
	// files after the worktree itself. A repo entry's list replaces the
	// global one.
	WorkspacePaths []WorkspacePath `json:"workspace_paths,omitempty"`
	// FullPaths shows absolute paths in human-facing output instead of
	// abbreviating the home directory to ~. Same effect as --full-paths.
	FullPaths *bool `json:"full_paths,omitempty"`
	// PostCreate commands run inside a newly created worktree, in order,
	// via sh -c. They come only from this user-owned config file — never
	// from the repository — and worktree metadata is passed as TH_*
	// environment variables rather than interpolated into the command.
	// A repo entry's list replaces the global one; [] disables.
	PostCreate []string `json:"post_create,omitempty"`
}

Settings are the options that can be set globally and overridden per repo.

func (Settings) CopyHooksEnabled

func (s Settings) CopyHooksEnabled() bool

CopyHooksEnabled reports whether copy_hooks is set and true.

func (Settings) EffectivePrefix

func (s Settings) EffectivePrefix() string

EffectivePrefix returns BranchPrefix with the separator applied, e.g. "peter" -> "peter/". A prefix already ending in the separator is not doubled. Empty if no prefix is configured.

func (Settings) FullPathsEnabled

func (s Settings) FullPathsEnabled() bool

FullPathsEnabled reports whether full_paths is set and true.

func (Settings) VSCodeOpenEnabled

func (s Settings) VSCodeOpenEnabled() bool

VSCodeOpenEnabled reports whether vscode_open is set and true.

func (Settings) VSCodeWorkspaceFileEnabled

func (s Settings) VSCodeWorkspaceFileEnabled() bool

VSCodeWorkspaceFileEnabled reports whether vscode_workspace_file is set and true.

func (Settings) WorktreePath

func (s Settings) WorktreePath(repo, branch string) (string, error)

WorktreePath expands the WorktreeDir template for repo and branch.

type WorkspacePath

type WorkspacePath struct {
	// Name is the folder's display name in VS Code. Optional.
	Name string `json:"name,omitempty"`
	// Path is the folder's location; a leading ~ expands to the home
	// directory, anything else is written as given.
	Path string `json:"path"`
}

WorkspacePath is one extra folder for generated .code-workspace files.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL