repos

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Nov 13, 2026 License: MIT Imports: 23 Imported by: 0

README

Local repository registry

This package owns the repository tables in the shared private (0600) app.sqlite application database. It stores what the user chose to review. It reads local git metadata only and contacts nothing; the daemon supplies the one GitHub lookup its HTTP handler uses.

Stored data

  • repositories(identity, settings): settings shared by every clone of a repository. identity is the lowercase owner/name on github.com and host/owner/name elsewhere. settings is JSON (automatic, decisions); a daily_cap, backend or model an older baum stored is ignored and dropped on the next write, and dropped from a request an older app sends: the harnesses and models are global preferences.

  • clones(id, path, common_dir, repository): registered working trees. A list reprobes each path and reports a changed or missing one unavailable without rewriting it.

  • picked(identity): repositories picked by name, possibly without a clone.

  • aliases(alias, repository): earlier github.com names GitHub forwards to a repository after a rename or transfer, recorded when a folder whose remote uses one is registered (AddForwarded). Open and OpenReadOnly load them into gitlocal (every baum command opens the registry read-only first), so in that process every remote URL using an earlier name reads as the current one (gitlocal.RemoteRepository, github.RepositoryFromRemote) and the clone is a clone of the repository everywhere. Clones registered under the earlier name move to the current one, which is picked once and takes the earlier name's settings while its own are still the default. Renames chain, and renaming back undoes them. The daemon asks GitHub again at startup, and a fix before it pushes for its repository (RecheckAliases): an alias GitHub now answers with another repository than the recorded one (a new one took the name) is dropped, so its remotes name that repository again; one it could not check or does not show the token is kept, but a fix does not push while one is: a repository the token cannot see may have taken the name. The remote is never rewritten. Repositories lists as earlier_names only those a registered clone's remote still uses, read from the clones' git configuration on each listing, so updating the remote clears it; the alias itself stays.

  • preferences(key, value): the global preferences as one JSON row. Its appearance object (theme, key_hints, page_modifier) stores the device’s General settings independently of the daemon’s loopback port. Its plan_usage.show object maps claude and codex to the person's choice of showing that plan's usage; a missing plan follows the backends in use (see planusage). Its decisions object (enabled, model) configures local decision capture; Settings.DecisionsEnabled combines it with the automatic master switch and the repository's decisions (nil is on). See decisionlog. Its review_time_limit_minutes and run_time_limit_minutes, when set (1 to MaxTimeLimit, 240), replace the config file's review_timeout and run_timeout in Preferences.Resolve; a value out of range keeps the file's and does not block saving other preferences.

  • prompt_overrides(repository, prompt_id, text, based_on, updated_at): custom review, fix and extraction prompts (ids from agent/prompt). They are stored only here and never read from repository content.

    • repository is '' (GlobalPrompts) for the global scope, else the repository's current lowercase identity. Callers pass that name; earlier alias names are not followed, as with RepositorySettings.
    • SetPromptOverride runs prompt.Validate; a rejection wraps ErrInvalidPrompt. It stores the prompt's built-in version in based_on.
    • SetPromptOverride and DeletePromptOverride require a picked repository (ErrNotPicked, checked in the transaction); the global scope needs none. DeletePromptOverride fails with ErrInvalidPrompt for an unknown id; deleting a missing row is no error.
    • ResolvePrompts picks per prompt id the repository's text, else the global one, else the built-in (absent from the returned prompt.Overrides), and reports a PromptSource for every id. A repository that is not picked gets only the global texts. A stored text that no longer passes prompt.Validate is skipped.
    • Unpick keeps the rows, so a re-pick sees them.
    • AddForwarded copies the earlier name's rows to the current name when the earlier name is still picked and the current name has no overrides (deliberately unlike settings, which copy only while they are the default). It then deletes the earlier name's rows in any case, because it is unpicked and another repository may later take the name.
    • A read-only registry reads no overrides while the table is missing, and sees them once a writer has created it.

A repository is picked exactly when it has a picked row. Adding a clone also picks its repository, and removing the clone keeps it picked with zero clones. A repository with no clone is still registered: RepositorySettings and automatic admission treat it as such, and only unpick revokes that. Work that needs a clone waits for one: discovery lists the repository's pull requests, but the job API answers needs_clone and automatic generation submits nothing until a clone is registered. Unpick deletes the repository's clones and its picked row but keeps the repositories row, so its settings survive a re-pick. Pick accepts only github.com owner/name; it reads no local git and checks nothing on GitHub.

The application database owns schema versioning. Pre-release registry files are not imported; a new registration follows the global automatic preference.

HTTP

Registry.Handler has no authentication; the daemon mounts it behind its authenticated host and origin checks. JSON is decoded strictly.

Route Result
GET /api/repos clones
GET /api/repos/check?path= whether a path can be registered
POST /api/repos {"path","settings"?,"repository"?} register a clone; optional repository uses any matching remote (400 {"message"})
DELETE /api/repos/{id} remove a clone (204, 404)
PUT /api/repos/{id}/settings replace the repository's settings
GET /api/repositories picked repositories, [{"repository","settings","clones":[]}]
POST /api/repositories {"repository","settings"} pick (400 on a bad name or settings)
DELETE /api/repositories/{owner}/{name} unpick (204, 404)
PUT /api/repositories/{owner}/{name}/settings replace settings (404 unless picked)
GET /api/repositories/{owner}/{name}/prompts {"prompts":[...]}, one entry per catalogue prompt with the repository's own custom_text/based_on/outdated/invalid/invalid_reason, source (what a run uses, as ResolvePrompts) and inherited_text (the valid global text, else the built-in; 404 unless picked)
PUT /api/repositories/{owner}/{name}/prompts/{id} {"text": string|null} set the repository's override; null or "" resets to inherit; answers the entry (400 {"message"} invalid text or body, 404 unknown id or not picked, 413 too large)

Only POST validates the name. DELETE and PUT only lowercase it and look it up, so a malformed owner/name answers 404, and an Enterprise identity added through add can be unpicked from the CLI.

Add files a clone under its first GitHub remote, origin first. AddFor(path, repository, settings) files it under repository when any of its GitHub remotes names it (a fork clone whose upstream is the picked repository), and fails with ErrNoMatchingRemote when none does. The fork's own repository is neither registered nor picked. A list reprobes a clone by its stored repository the same way, so such a clone stays available while some remote names that repository. Pull request commits a clone lacks are fetched by generation from the remote whose URL matches the registered repository, not origin, into refs/baum/pull/<N>/.

Cloning a picked repository is served beside these routes by internal/githubrepos (the registry package contacts nothing): GET /api/repositories/{owner}/{name}/clone-target (the default folder), POST /api/repositories/{owner}/{name}/clone {"dir"?} (picks the repository if needed, clones in the background and registers the clone with AddFor; 202, 400, 409) and GET .../clone (the current or last state).

The explicit Choose folder action supplies repository to POST /api/repos, which calls AddFor. When no remote names the repository, HandlerWith's CurrentName (the daemon asks GitHub) checks each GitHub remote, origin first; the first GitHub answers with the repository's current name is registered through AddForwarded. Otherwise the request fails with 400 and a JSON message naming the repositories the remotes use, or saying GitHub could not be asked. Handler has no CurrentName and refuses such folders. Omitting it preserves the standalone path registration behavior.

AddFor moves a path already registered to another repository to the new one. The daemon's clone finder uses AttachFound instead, which never changes what is stored: it fails with ErrClonedElsewhere when the path or its repository directory belongs to another repository, and with ErrNotPicked unless the repository is picked, checked in the same transaction, so an unpick in between is not undone. PickedWithoutClones (picked repositories with no clone row), CloneRows (clones as stored, available false) and RepositoryRows (Repositories with clones as stored) read the registry only and run no git, unlike List and Repositories, which probe every clone.

A probe runs git in the clone only when something its answer is read from changed. The process keeps each clone's last availability with a stamp of:

  • that its directory exists;
  • its .git entry's kind, and for a linked worktree's file its contents;
  • its common directory's config size and modification time, where the remotes live.

The modification times of the directory and its .git directory are not part of the stamp: they move on every index write and new file without changing the answer. Concurrent misses for one clone share a single probe.

While the stamp is unchanged the answer is reused, for at most ProbeMaxAge (5 minutes). A rewrite that only global git configuration makes, such as url.insteadOf, therefore shows within that time. A clone whose directory or .git is gone is unavailable without running git.

Settings PUTs replace the whole object and require automatic, null for the default. A daily_cap an older app still sends, in a settings PUT or in the settings of a POST, is dropped rather than refused: baum sets no spending limits.

CLI

baum internal repos add <path> registers an existing clone for desktop onboarding. Repository selection, removal and settings are managed through the desktop app and the authenticated HTTP routes above. The command changes no Git configuration or hooks and starts no daemon.

A registration the daemon stores (POST /api/repos, AddFor, AttachFound, a cloned repository) calls Registry.Registered, which the daemon sets to ensure baum's Git hook dispatchers in the clone in the background (githooks). It never fails or waits for the registration. A registry opened elsewhere, such as the CLI's, has no such hook. git config baum.hooks false in a clone opts it out: the daemon takes the dispatchers out and restores the hooks they replaced. Remove and Unpick call Registry.Removed for each clone they delete, and the daemon then does the same, unless a registered clone, the same one registered again included, shares the clone's path or common Git directory; the daemon reads the registry again before it installs or restores, so a sweep cannot reinstall hooks of a clone removed meanwhile. A removal before the service starts is restored when it does.

Documentation

Overview

Package repos stores explicitly registered local clones and repository settings.

Index

Constants

View Source
const (
	PullRequestsAuthored  = "authored"
	PullRequestsRequested = "requested"
	// PullRequestsAll covers every open pull request in the repository.
	PullRequestsAll = "all"
)

The PullRequests choices besides both.

View Source
const GlobalPrompts = ""

GlobalPrompts is the repository argument naming the global scope.

View Source
const MaxJobConcurrency = 4

MaxJobConcurrency is the most jobs the daemon runs at once besides questions to a review's agent, and the default. A person lowers it when parallel agents load the computer too much.

View Source
const MaxTimeLimit = 240

MaxTimeLimit is the longest time limit, in minutes, the app sets.

View Source
const ProbeMaxAge = 5 * time.Minute

ProbeMaxAge bounds how long a clone's availability is reused while nothing it is read from changed: a change only global git configuration makes, such as a url.insteadOf rewrite, shows within this time.

Variables

View Source
var (
	// ErrNotPicked reports a repository that is not picked.
	ErrNotPicked = errors.New("repository is not picked")
	// ErrClonedElsewhere reports a working tree, or a repository directory,
	// already registered to another repository.
	ErrClonedElsewhere = errors.New("clone is registered to another repository")
)

Errors of AttachFound.

View Source
var ErrInvalidPrompt = errors.New("invalid prompt")

ErrInvalidPrompt wraps the reason prompt.Validate (or an unknown id) rejected a custom prompt, fit to show the author; a host maps it to 400.

View Source
var ErrInvalidRepository = errors.New("repository must be a github.com owner/name")

ErrInvalidRepository reports a name that is not a github.com owner/name.

View Source
var ErrNoMatchingRemote = errors.New("working tree has no remote for that repository")

ErrNoMatchingRemote reports a working tree none of whose GitHub remotes names the requested repository.

View Source
var ErrNotFound = errors.New("registered clone or picked repository not found")

ErrNotFound reports a clone or picked repository the registry does not hold.

View Source
var ErrNotWorkingTree = errors.New("path is unavailable or is not a git working tree")

ErrNotWorkingTree reports a path that is missing or not in a git working tree.

Functions

func Path

func Path() (string, error)

func ValidateTimeLimit

func ValidateTimeLimit(minutes int) error

ValidateTimeLimit accepts zero (the config file's) or 1 to MaxTimeLimit minutes.

Types

type AppearancePreferences

type AppearancePreferences struct {
	Theme    string `json:"theme,omitempty"`
	KeyHints *bool  `json:"key_hints,omitempty"`
	// PageModifier is the key held with 1 to 8 to open the sidebar's pages:
	// "meta", "ctrl" or "alt"; empty is the platform's command key.
	PageModifier string `json:"page_modifier,omitempty"`
}

AppearancePreferences are device choices kept independently of the daemon HTTP origin.

type Clone

type Clone struct {
	ID         string   `json:"id"`
	Path       string   `json:"path"`
	CommonDir  string   `json:"common_dir"`
	Repository string   `json:"repository"`
	Settings   Settings `json:"settings"`
	Available  bool     `json:"available"`
}

func Inspect

func Inspect(ctx context.Context, path string) (Clone, error)

Inspect reports the clone a path would register as, or why it cannot be registered, without registering it.

type CurrentName

type CurrentName func(ctx context.Context, repository string) (string, error)

CurrentName is the lower-case owner/name a github.com repository has now; the daemon asks GitHub, which answers an earlier name it forwards with the current one. The registry itself contacts nothing.

type DecisionPreferences

type DecisionPreferences struct {
	Enabled *bool           `json:"enabled,omitempty"`
	Backend *config.Backend `json:"backend,omitempty"`
	Model   *string         `json:"model,omitempty"`
	Effort  *string         `json:"effort,omitempty"`
}

DecisionPreferences are the global choices for local decision capture and the feature log, the data extraction the app's settings name. A nil Enabled is on. A nil Backend follows the reviews' backend. Model, when set, replaces the backend's default decision model. Effort is the reasoning effort (config.Efforts), empty or nil for the harness's own.

type PlanUsagePreferences

type PlanUsagePreferences struct {
	Show map[string]bool `json:"show,omitempty"`
}

PlanUsagePreferences are the plans the person chose to show or hide in plan usage, by provider ("claude", "codex"). A provider with no entry follows the backends baum uses, so a choice survives backend changes.

type Preferences

type Preferences struct {
	// Automatic is the default for repositories without an explicit choice.
	Automatic bool `json:"automatic"`
	// Backend and Model, when set, replace the config file's for generation
	// in the app; a repository's own settings still override them.
	Backend *config.Backend `json:"backend,omitempty"`
	Model   *string         `json:"model,omitempty"`
	// Effort is the reviews' reasoning effort (config.Efforts), empty or nil
	// for the harness's own.
	Effort *string `json:"effort,omitempty"`
	// FixBackend, FixModel and FixEffort choose the agent that fixes pull
	// requests (ResolveFix). A nil FixBackend means the same as reviews; an
	// empty FixModel is the fix backend's default model and an empty
	// FixEffort its own effort.
	FixBackend *config.Backend `json:"fix_backend,omitempty"`
	FixModel   *string         `json:"fix_model,omitempty"`
	FixEffort  *string         `json:"fix_effort,omitempty"`
	// PullRequests narrows which pull requests get automatic reviews:
	// PullRequestsAuthored, PullRequestsRequested, PullRequestsAll, or empty
	// for both authored and requested.
	PullRequests string `json:"pull_requests,omitempty"`
	// AgentEnv, when it sets any variable, replaces the config file's
	// agent_env (config.Config.AgentEnv).
	AgentEnv map[string]string `json:"agent_env,omitempty"`
	// Appearance survives daemon restarts and changes to its loopback origin.
	Appearance AppearancePreferences `json:"appearance,omitzero"`
	// Decisions configures local decision capture.
	Decisions DecisionPreferences `json:"decisions,omitzero"`
	// PlanUsage chooses which plans plan usage shows.
	PlanUsage PlanUsagePreferences `json:"plan_usage,omitzero"`
	// JobConcurrency, when set, is how many jobs the daemon runs at once
	// besides questions to a review's agent; Concurrency resolves it.
	JobConcurrency int `json:"job_concurrency,omitempty"`
	// ReviewTimeLimit and RunTimeLimit, in minutes, when set replace the
	// config file's review_timeout and run_timeout (Resolve): how long a
	// review, and any other agent run, may take.
	ReviewTimeLimit int `json:"review_time_limit_minutes,omitempty"`
	RunTimeLimit    int `json:"run_time_limit_minutes,omitempty"`
}

Preferences are the registry's global choices, edited in the app. Fields an older baum saved and this one dropped, such as cursor_agent_acknowledged, are ignored on read and gone after the next write.

func DefaultPreferences

func DefaultPreferences() Preferences

DefaultPreferences apply until the user changes them: automatic generation on.

func (Preferences) Concurrency

func (p Preferences) Concurrency() int

Concurrency is how many jobs run at once: JobConcurrency, or MaxJobConcurrency when it is unset or out of range (a hand edit, or a newer baum's).

func (Preferences) Covers

func (p Preferences) Covers(authored, requested bool) bool

Covers reports whether automatic reviews cover a pull request the viewer authored or was asked to review, as PullRequests chooses.

func (Preferences) Resolve

func (p Preferences) Resolve(global config.Config) config.Config

Resolve overlays the app's backend, model, agent environment and time limits on the config file's.

func (Preferences) ResolveExtraction

func (p Preferences) ResolveExtraction(cfg config.Config) config.Config

ResolveExtraction gives the config data extraction runs with, from cfg, the config resolved for reviews: the extraction's own effort. Its backend and model are decisionlog's to resolve.

func (Preferences) ResolveFix

func (p Preferences) ResolveFix(review config.Config) config.Config

ResolveFix gives the config a fix runs with, from review, the config already resolved for reviews. A set FixBackend replaces the review backend, model and effort, and takes FixModel and FixEffort (empty for the backend's own); without one the fix follows the reviews.

func (Preferences) Validate

func (p Preferences) Validate() error

Validate accepts an empty Model, unlike Settings: it means the backend's default even when the config file names a model.

func (Preferences) ValidateChange

func (p Preferences) ValidateChange(prev Preferences) error

ValidateChange is Validate for preferences saved over prev: the desktop app offers Claude Code and Codex only, so a backend chosen now must be one of them. A retired backend already stored (cursor-agent or anthropic, from a pre-release version) does not block saving other settings; the daemon refuses the jobs that use it.

type PromptEntry added in v0.2.0

type PromptEntry struct {
	ID             string  `json:"id"`
	Title          string  `json:"title"`
	Group          string  `json:"group"`
	UsedBy         string  `json:"used_by"`
	DefaultText    string  `json:"default_text"`
	DefaultVersion string  `json:"default_version"`
	CustomText     *string `json:"custom_text"`
	BasedOn        *string `json:"based_on"`
	Outdated       bool    `json:"outdated"`
	// Invalid marks a stored text that no longer passes validation: it is
	// shown but not used by runs.
	Invalid       bool               `json:"invalid"`
	InvalidReason *string            `json:"invalid_reason"`
	SafetyRules   []PromptSafetyRule `json:"safety_rules"`
	MissingRules  []string           `json:"missing_safety_rules"`
	Source        PromptSource       `json:"source,omitempty"`
	InheritedText *string            `json:"inherited_text,omitempty"`
}

PromptEntry is one catalogue prompt as the app shows it in a scope: the global one, or one repository's (then Source and InheritedText are set).

type PromptOverride added in v0.2.0

type PromptOverride struct {
	ID   prompt.ID
	Text string
	// BasedOn is the built-in version (Entry.DefaultVersion) current when the
	// text was saved, so a later change of the built-in can be flagged.
	BasedOn   string
	UpdatedAt time.Time
}

PromptOverride is a custom prompt text stored locally for one scope.

type PromptSafetyRule added in v0.2.0

type PromptSafetyRule struct {
	ID    string `json:"id"`
	Label string `json:"label"`
	Text  string `json:"text"`
}

PromptSafetyRule is a safety rule of a prompt, for display.

type PromptSource added in v0.2.0

type PromptSource string

PromptSource says where a prompt's effective text comes from.

const (
	PromptSourceDefault    PromptSource = "default"
	PromptSourceGlobal     PromptSource = "global"
	PromptSourceRepository PromptSource = "repository"
)

type Registry

type Registry struct {
	// Registered, when set, is called with each clone a registration stored
	// (Add, AddFor, AddForwarded and AttachFound), after it is stored. It
	// must not block: the daemon uses it to start work on the new clone. A
	// registry the CLI opens has none.
	Registered func(Clone)
	// Removed, when set, is called with each clone Remove or Unpick deleted,
	// after it is deleted, and must not block.
	Removed func(Clone)
	// contains filtered or unexported fields
}

func Open

func Open(path string) (*Registry, error)

Open opens repository tables in the shared application database.

func OpenReadOnly

func OpenReadOnly(path string) (*Registry, error)

OpenReadOnly opens an existing registry only to list it. Unlike Open it creates no directory, database or table and changes no file mode, and SQLite opens the file read-only, so it never writes it. In WAL mode SQLite creates its -shm and -wal coordination files beside the database when missing (see appdb.Open). A missing file is an error wrapping fs.ErrNotExist; a file without tables lists no clones.

func (*Registry) Add

func (r *Registry) Add(ctx context.Context, path string, settings *Settings) (Clone, error)

Add registers an existing clone. Nil settings preserve existing settings; explicit settings replace the settings shared by all its repository's clones.

func (*Registry) AddFor

func (r *Registry) AddFor(ctx context.Context, path, repository string, settings *Settings) (Clone, error)

AddFor registers an existing clone for repository (github.com owner/name) when any of its GitHub remotes names it, not only origin: a fork clone whose upstream remote is the repository is filed under the repository, and the fork's own repository is neither registered nor picked. It fails with ErrNoMatchingRemote when no remote names the repository. Settings are as for Add.

func (*Registry) AddForwarded

func (r *Registry) AddForwarded(ctx context.Context, path, repository, alias string, settings *Settings) (Clone, error)

AddForwarded registers a clone for repository, as AddFor does, whose remote uses alias, an earlier name GitHub forwards to repository, which the caller has checked. The alias is recorded first: from then on remote URLs using it read as repository (gitlocal.RenamedTo), so the clone stays a clone of repository everywhere, until RecheckAliases finds GitHub no longer forwards it.

func (*Registry) AddPatch

func (r *Registry) AddPatch(ctx context.Context, path string, edit func(Settings) (Settings, error)) (Clone, error)

AddPatch atomically registers a clone and applies a settings edit. The edit runs under the writer transaction, so omitted fields cannot lose another process's concurrent edits. It must not call back into the registry.

func (*Registry) AttachFound

func (r *Registry) AttachFound(ctx context.Context, path, repository string) (Clone, error)

AttachFound registers a clone the daemon found for a picked repository, as AddFor does, but never changes what is already stored: it fails with ErrNotPicked unless the repository is picked (checked in the same transaction, so an unpick in between is not undone) and with ErrClonedElsewhere when the path or its repository directory is registered to another repository, which AddFor would move.

func (*Registry) CloneRows

func (r *Registry) CloneRows(ctx context.Context) ([]Clone, error)

CloneRows lists the registered clones exactly as stored, without probing them: Available is false throughout. It runs no git.

func (*Registry) Close

func (r *Registry) Close() error

func (*Registry) DeletePromptOverride added in v0.2.0

func (r *Registry) DeletePromptOverride(ctx context.Context, repository string, id prompt.ID) error

DeletePromptOverride removes the override of id for a scope; a missing one is not an error. An unknown id fails with ErrInvalidPrompt and a non-empty repository must be picked (ErrNotPicked).

func (*Registry) Handler

func (r *Registry) Handler() http.Handler

Handler exposes the registry API for the future local UI host. It does not listen or authenticate: the host MUST mount it behind its authenticated, host/origin-checked middleware. Never mount this on the public view server.

func (*Registry) HandlerWith

func (r *Registry) HandlerWith(current CurrentName) http.Handler

HandlerWith is Handler, also registering a folder for a repository when its remote uses an earlier name that current reports GitHub forwards to it.

func (*Registry) List

func (r *Registry) List(ctx context.Context) ([]Clone, error)

func (*Registry) Pick

func (r *Registry) Pick(ctx context.Context, repository string, settings *Settings) (Repository, error)

Pick registers a github.com repository by owner/name without a local clone. Nil settings keep the existing settings, or the default for a new repository; explicit settings replace them. Picking again is a no-op.

func (*Registry) PickedWithoutClones

func (r *Registry) PickedWithoutClones(ctx context.Context) ([]string, error)

PickedWithoutClones lists the picked repositories that have no clone registered. It reads the registry only and runs no git, so it is cheap enough to ask for every hook event.

func (*Registry) Preferences

func (r *Registry) Preferences(ctx context.Context) (Preferences, error)

Preferences reads the global preferences: DefaultPreferences until saved.

func (*Registry) PromptEntries added in v0.2.0

func (r *Registry) PromptEntries(ctx context.Context, repository string) ([]PromptEntry, error)

PromptEntries builds the entries of a scope ("" is global), one per catalogue id in catalogue order. custom_text, based_on and outdated come from that scope's own rows. For a repository, inherited_text is the global override's text, else the built-in text, and source says which text a run uses. The repository must be picked (ErrNotPicked).

func (*Registry) PromptOverrides added in v0.2.0

func (r *Registry) PromptOverrides(ctx context.Context, repository string) (map[prompt.ID]PromptOverride, error)

PromptOverrides reads the overrides stored for one scope: repository "" is the global scope. A database without the table has none.

func (*Registry) RecheckAliases

func (r *Registry) RecheckAliases(ctx context.Context, repository string, current func(context.Context, github.Repository) (string, error)) (unconfirmed []string, err error)

RecheckAliases asks GitHub (current) again about the recorded earlier names of repository, or of every repository when it is "", and drops each one it now answers with another repository than the recorded one does, as when a new repository took the name: remotes using it then name that one. One it could not check or does not show the token is kept, and returned as unconfirmed: a repository the token cannot see may have taken it.

func (*Registry) Remove

func (r *Registry) Remove(ctx context.Context, idOrPath string) error

Remove accepts an ID or path, including a path that no longer exists.

func (*Registry) Repositories

func (r *Registry) Repositories(ctx context.Context) ([]Repository, error)

Repositories lists every picked repository by identity, with its clones probed for availability as List does.

func (*Registry) RepositoryRows

func (r *Registry) RepositoryRows(ctx context.Context) ([]Repository, error)

RepositoryRows is Repositories without probing the clones: Available is false throughout. It runs no git.

func (*Registry) RepositorySettings

func (r *Registry) RepositorySettings(ctx context.Context, repository string) (Settings, bool, error)

RepositorySettings reads one repository's shared settings without probing its clones; false means the repository is not picked.

func (*Registry) ResolvePrompts added in v0.2.0

func (r *Registry) ResolvePrompts(ctx context.Context, repository string) (prompt.Overrides, map[prompt.ID]PromptSource, error)

ResolvePrompts picks, for every catalogue prompt, the repository's override, else the global one, else the built-in text. Overrides holds only the overridden prompts; sources has every catalogue id. A repository that is not picked (or "") gets only the global overrides: its rows, kept after an unpick, apply again once it is picked. Stored texts that fail prompt.Validate are skipped. Pass the repository's current lower-case name; earlier alias names are not followed.

func (*Registry) ServePromptPut added in v0.2.0

func (r *Registry) ServePromptPut(w http.ResponseWriter, req *http.Request, repository, id string)

ServePromptPut answers PUT .../prompts/{id} for a scope ("" is global): it stores the text, or resets the prompt for null or "", and answers the updated entry. An unknown id and an unpicked repository are 404, a body that is too large 413, a malformed one (unknown or missing fields, trailing data) or an invalid text 400, each with {"message": ...}.

func (*Registry) ServePrompts added in v0.2.0

func (r *Registry) ServePrompts(w http.ResponseWriter, req *http.Request, repository string)

ServePrompts answers GET .../prompts for a scope ("" is global) with {"prompts": [...]}; an unpicked repository is a 404.

func (*Registry) SetPromptOverride added in v0.2.0

func (r *Registry) SetPromptOverride(ctx context.Context, repository string, id prompt.ID, text string) (PromptOverride, error)

SetPromptOverride validates and stores text as the override of id for a scope ("" is global), recording the current built-in version as BasedOn. A non-empty repository must be picked (ErrNotPicked). A rejected text fails with an error wrapping ErrInvalidPrompt.

func (*Registry) Unpick

func (r *Registry) Unpick(ctx context.Context, repository string) error

Unpick removes a picked repository's clones and its picked row. The repositories row stays, as in Remove, so its settings survive a later pick.

func (*Registry) Update

func (r *Registry) Update(ctx context.Context, id string, s Settings) error

Update replaces shared repository settings without needing an available clone.

func (*Registry) UpdatePreferences

func (r *Registry) UpdatePreferences(ctx context.Context, edit func(Preferences) Preferences) (Preferences, error)

UpdatePreferences atomically edits the global preferences. The edit runs under the writer transaction and must not call back into the registry.

func (*Registry) UpdateRepository

func (r *Registry) UpdateRepository(ctx context.Context, repository string, s Settings) error

UpdateRepository replaces a picked repository's shared settings by identity.

type RemoteMismatchError

type RemoteMismatchError struct {
	Repository string
	Remotes    []string
	// Unchecked is set when GitHub could not be asked whether a remote uses
	// an earlier name of Repository.
	Unchecked bool
}

RemoteMismatchError is ErrNoMatchingRemote, naming the repositories the working tree's GitHub remotes name instead, origin's first; none when it has no GitHub remote.

func (*RemoteMismatchError) Error

func (e *RemoteMismatchError) Error() string

func (*RemoteMismatchError) Is

func (e *RemoteMismatchError) Is(target error) bool

type Repository

type Repository struct {
	Repository string   `json:"repository"`
	Settings   Settings `json:"settings"`
	Clones     []Clone  `json:"clones"`
	// EarlierNames are recorded names GitHub forwards to the repository that
	// a clone's remote still uses, read from the clones' configuration on
	// each listing (AddForwarded records them).
	EarlierNames []string `json:"earlier_names,omitempty"`
}

Repository is a picked repository with its settings and registered clones, of which there may be none.

type Settings

type Settings struct {
	Automatic *bool `json:"automatic"`
	// Decisions is the repository's choice for local decision capture under
	// the global switches (see DecisionsEnabled): nil and true follow them,
	// false turns the repository off.
	Decisions *bool `json:"decisions,omitempty"`
}

Settings are shared by all clones of a repository. Automatic is the repository's choice under the global master switch (see AutomaticEnabled): nil follows it, false turns the repository off, true is an explicit on that still stops while the global switch is off. Registration itself starts no generation. A daily_cap, backend or model an older baum stored is ignored on read and dropped on the next write: baum sets no spending limits, since it cannot price what a subscription bills, and the harnesses and models are global (Preferences).

func (Settings) AutomaticEnabled

func (s Settings) AutomaticEnabled(p Preferences) bool

AutomaticEnabled reports whether the daemon generates reviews of this repository automatically. The global preference is a master switch: off stops every repository, whatever its choice; on, only an explicit false turns a repository off.

func (Settings) DecisionsEnabled

func (s Settings) DecisionsEnabled(p Preferences) bool

DecisionsEnabled reports whether the daemon captures the decisions of this repository's agent sessions: the automatic master switch (which the tray's pause turns off) and the decisions switch are both on, and the repository has not turned capture off.

Jump to

Keyboard shortcuts

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