repos

package
v0.16.2 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package repos holds the connected-repos machinery for cross-repo references: the user-global configuration naming which repositories this user is connected to, and the managed read-only clone caches those connections resolve against. The package reads no ambient state — the config path and cache root arrive as an explicit Locations value, resolved once at the composition root (repos.DefaultLocations for the XDG convention). Pure reads live on Registry; the side-effectful cache lifecycle (clone, pull, config save) lives on Manager, orchestrated by handlers that invalidate the read side's GraphSource on completion.

Index

Constants

View Source
const DefaultPullCooldown = 15 * time.Minute

DefaultPullCooldown gates how often a read triggers a cache pull.

Variables

This section is empty.

Functions

func DeclaredRepoID

func DeclaredRepoID(dir string) (string, error)

DeclaredRepoID reads the repo_id the cached repo declares in its committed .sdd/config.yaml. Verification for `sdd repo add`: the connection is only valid when the target declares the identity the caller registers it under.

func GraphDir

func GraphDir(dir string) (string, error)

GraphDir resolves the cached repo's graph directory from its committed config, defaulting to the conventional location.

func IsCloned

func IsCloned(dir string) bool

IsCloned reports whether the cache dir holds a git clone.

func LegacyIndexDir

func LegacyIndexDir(dir string) string

LegacyIndexDir is the pre-store per-repo index location inside a clone cache (<cache>/.index) — kept only so `sdd init` can migrate an existing build into the machine-global store. Nothing writes here anymore.

func SaveConfigTo

func SaveConfigTo(path string, cfg *GlobalConfig) error

SaveConfigTo writes a user-global config to an explicit path, creating parent directories as needed. 0600 — the embedding block may carry API keys.

Types

type ConnectedRepo

type ConnectedRepo struct {
	RepoID   string `yaml:"repo_id"`
	CloneURL string `yaml:"clone_url"`
}

ConnectedRepo names one connection: the canonical repo identity and the URL its cache clones from. CloneURL is per-user (ssh vs https), RepoID is identical for everyone (declared in the target repo's committed config).

type Git

type Git interface {
	// Clone clones url into dir.
	Clone(ctx context.Context, url, dir string) error
	// PullFFOnly pulls the checkout at dir, fast-forward only — the cache is
	// read-only, so a non-ff state means the remote rewrote history; surface
	// that rather than merging.
	PullFFOnly(ctx context.Context, dir string) error
}

Git is the narrow git surface the cache lifecycle needs. The production implementation is internal/git's exec adapter; tests inject fakes.

type GlobalConfig

type GlobalConfig struct {
	model.BaseConfig `yaml:",inline"`

	// Repos is the per-user resolution of connected repositories: for each
	// repo_id, how this machine reaches it (clone URL, homedir cache). The
	// committed per-repo `dependencies` list declares what a graph needs;
	// this list resolves how — which is why it is global-only.
	Repos []ConnectedRepo `yaml:"repos,omitempty"`
}

GlobalConfig is the user-global SDD configuration. It embeds the shared user/machine settings (model.BaseConfig — participant, llm, embedding, sync) that seed the config overlay for every repo on this machine; its embedding config doubles as the global embedder every connected repo's index is built with — one vector space so cosine scores are comparable across repos (a repo indexed under a different fingerprint is excluded from cross-graph search and flagged by lint). Hand-editable YAML underneath; per-repo-only fields (repo_id above all) do not exist on this schema, so a misplaced one is a parse error.

func LoadConfigFrom

func LoadConfigFrom(path string) (*GlobalConfig, error)

LoadConfigFrom reads a user-global config from an explicit path. A missing file is not an error — it yields an empty config (no connections). Unknown keys are an error: a setting placed in the wrong file must surface at load time, never be silently dropped (d-cpt-6cq's fail-loud rule).

func (*GlobalConfig) AddRepo

func (c *GlobalConfig) AddRepo(repo ConnectedRepo) error

AddRepo registers a connection. A connection with the same repo_id must not already exist — re-registering is a remove + add, never a silent overwrite.

func (*GlobalConfig) Connected

func (c *GlobalConfig) Connected(repoID string) (ConnectedRepo, bool)

Connected returns the connection for repoID, if present.

func (*GlobalConfig) ConnectedByURL

func (c *GlobalConfig) ConnectedByURL(cloneURL string) (ConnectedRepo, bool)

ConnectedByURL returns the connection whose clone URL matches cloneURL, if any — the `repo add` fast-path check (already connected under this URL), shared by the handler and the CLI's view-gate so both read one definition of "already connected".

func (*GlobalConfig) RemoveRepo

func (c *GlobalConfig) RemoveRepo(repoID string) bool

RemoveRepo drops the connection for repoID, reporting whether it existed.

func (*GlobalConfig) SelectRepoIDs

func (c *GlobalConfig) SelectRepoIDs(named []string, all bool) ([]string, error)

SelectRepoIDs resolves a caller's repo selection against the connected set: all=true means every connected repo; an explicitly named repo that is not connected is an error — silent narrowing would misreport coverage. An empty selection resolves to nil.

func (*GlobalConfig) UnconnectedDependencies

func (c *GlobalConfig) UnconnectedDependencies(deps []string) []string

UnconnectedDependencies returns the declared dependencies (committed repo_ids) that have no connection in this user-global config — the gap `sdd init` reports after a fresh clone, since the clone_url half of a connection is per-user and cannot ride in the committed declaration.

type Locations

type Locations struct {
	// ConfigPath is the user-global config file
	// (default $XDG_CONFIG_HOME/sdd/config.yaml).
	ConfigPath string
	// CacheRoot is the base directory for connected-repo clone caches
	// (default $XDG_CACHE_HOME/sdd).
	CacheRoot string
}

Locations names the user-global places the connected-repos machinery works against: the config file and the cache root. Resolved once at the composition root and passed down explicitly — tests point both at temp dirs, no environment involved.

func DefaultLocations

func DefaultLocations() (Locations, error)

DefaultLocations resolves the conventional locations: the XDG base directories, defaulting to ~/.config and ~/.cache. Implemented against the XDG convention directly (not os.UserConfigDir) so the paths are uniform across platforms and match the documented locations. This is the only place the package touches the environment — called by composition roots, never by library code.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager owns the side-effectful half of the connected-repos machinery: cache clone and pull, and config writes. It wraps the pure Registry and is the dependency handlers get injected — the write-side counterpart to the finder-injected Registry.

func NewManager

func NewManager(reg *Registry, git Git) *Manager

NewManager builds a Manager over the registry and the git dependency.

func (*Manager) CooldownPull

func (m *Manager) CooldownPull(ctx context.Context, dir string, cooldown time.Duration) (bool, error)

CooldownPull pulls the cache when the last attempt is older than cooldown. Reports whether a pull ran. The marker is touched on every attempt — cooldown bounds attempts, not successes — but a failed pull still returns its error (fail loud; the caller decides whether stale reads may proceed).

func (*Manager) EnsureCloned

func (m *Manager) EnsureCloned(ctx context.Context, repo ConnectedRepo, dir string) (bool, error)

EnsureCloned clones repo.CloneURL into dir when no clone is present yet. Reports whether a clone ran (false: the cache already existed).

func (*Manager) ForcePull

func (m *Manager) ForcePull(ctx context.Context, dir string) error

ForcePull pulls the cache unconditionally (fast-forward only).

func (*Manager) Registry

func (m *Manager) Registry() *Registry

Registry exposes the pure read surface, so a Manager-holding handler reads through the same paths the finders do.

func (*Manager) Save

func (m *Manager) Save(cfg *GlobalConfig) error

Save writes the user-global config to the registry's config path.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry is the pure read surface over the connected-repos state: which repos are connected and where their caches live. It is the dependency the read side (finders) gets injected — it carries no way to clone, pull, or save, so finder purity is enforced by the type, not by discipline. The side-effectful lifecycle lives on Manager.

func NewRegistry

func NewRegistry(loc Locations) *Registry

NewRegistry builds a Registry over explicit locations. Composition roots pass DefaultLocations(); tests pass temp dirs.

func (*Registry) CacheDir

func (r *Registry) CacheDir(repoID string) (string, error)

CacheDir resolves a connected repo's clone location under the cache root. The repo-id's host/path shape nests naturally under the root.

func (*Registry) CacheRoot

func (r *Registry) CacheRoot() string

CacheRoot is the base directory for connected-repo clone caches.

func (*Registry) ConfigPath

func (r *Registry) ConfigPath() string

ConfigPath returns the user-global config file path. Exposed for the comment-preserving `sdd config set` upsert, which patches the file bytes in place rather than round-tripping through Save (which would drop comments).

func (*Registry) Load

func (r *Registry) Load() (*GlobalConfig, error)

Load reads the user-global config. Deliberately lazy — read per call, not snapshotted at construction — so a long-lived process (the MCP server) sees a repo connected from another terminal without a restart. A missing file yields an empty config.

func (*Registry) SelectRepoIDs

func (r *Registry) SelectRepoIDs(named []string, all bool) ([]string, error)

SelectRepoIDs resolves a caller's repo selection against the connected set (see GlobalConfig.SelectRepoIDs).

Jump to

Keyboard shortcuts

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