deps

package
v0.6.0-2a Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package deps models a factory's dependencies. It reads the unobin.manifest, which lists each direct dependency and the lowest version the factory accepts for it, and drives pkg/resolve to fetch them.

Index

Constants

View Source
const CurrentLockVersion = 1

CurrentLockVersion is the schema version this package reads and writes. A different version errors on read, since this build cannot guarantee a correct interpretation.

View Source
const LockFileName = "unobin.lock"

LockFileName is the standard filename for a factory's dependency lock.

View Source
const ManifestFileName = "unobin.manifest"

ManifestFileName is the standard filename for a factory's dependency manifest.

Variables

This section is empty.

Functions

func EncodeLock added in v0.6.0

func EncodeLock(lock *Lock) ([]byte, error)

EncodeLock serializes lock to bytes with a trailing newline.

func EncodeManifest added in v0.6.0

func EncodeManifest(m *Manifest) []byte

EncodeManifest renders a manifest as unobin.manifest source. Entries in each block are sorted by dependency id for stable diffs. An empty requires block is still written; an empty replace block is omitted.

func FindManifestDir added in v0.6.0

func FindManifestDir(start string) (string, error)

FindManifestDir walks up from start to the nearest ancestor directory holding a unobin.manifest and returns that directory: the root of the project that governs start. start may be any path inside the project, a directory or a file. It stops at the filesystem root and returns an error wrapping fs.ErrNotExist when no manifest is found.

func Highest added in v0.6.0

func Highest(vs []string) string

Highest returns the greatest version in vs by semver order, or "" when vs is empty.

func ImportedRepos added in v0.6.0

func ImportedRepos(root string) (map[Dependency]bool, error)

ImportedRepos scans every .ub file under root and returns the set of repositories named by remote imports. The version on an import is not read here: a repository's version floor lives in unobin.manifest, not in the import string. Local imports are intra-project and contribute no repository. Hidden directories (a leading dot, such as .git) are skipped.

func Resolve added in v0.6.0

func Resolve(root *Manifest, fetch Fetcher) (map[Dependency]string, error)

Resolve runs minimal version selection over the dependency graph rooted at a manifest. It selects the highest floor for each dependency, fetches it at that version to read its own requirements, and repeats until the selection stops changing. A dependency whose version is later raised is re-fetched, since a higher version may declare different requirements; the walk terminates at any dependency with no manifest. The result maps each dependency to its selected version -- the lock, keyed per imported library, is built separately by the import walk.

func ResolveVersion added in v0.6.0

func ResolveVersion(dep Dependency, query string, tags []string) (string, error)

ResolveVersion turns a `deps get` query into a concrete version of dep, chosen among the repository's tags. An empty query or "latest" picks the highest available version; a full version (vX.Y.Z) is used as-is once confirmed present; a partial version (v1 or v1.2) picks the highest available version under that prefix.

func Verify added in v0.6.0

func Verify(lock *Lock, resolver resolve.Resolver) ([]string, error)

Verify re-fetches every ub-kind dependency in lock at its pinned commit and checks the content hash against the recorded one. A mismatch means the source changed under a pinned commit. Go dependencies are skipped: their integrity rides the generated go.sum, not a content hash here. It returns one message per dependency whose hash no longer matches, in id order.

func Versions added in v0.6.0

func Versions(dep Dependency, tags []string) []string

Versions returns the versions of dep found among a repository's tags, in increasing semver order. A tag qualifies only when it carries dep's prefix and the remainder is a valid semver string, so tags for other subdirectories and non-semver tags are ignored. The prefix is stripped: each returned element is a bare version, the form a manifest records.

func WriteLock added in v0.6.0

func WriteLock(path string, lock *Lock) error

WriteLock serializes lock and atomically replaces the file at path. The output is pretty-printed JSON with sorted keys for stable diffs.

func WriteManifest added in v0.6.0

func WriteManifest(path string, m *Manifest) error

WriteManifest serializes m and atomically replaces the file at path.

Types

type Dependency

type Dependency struct {
	URL    string
	Subdir string
}

Dependency identifies an importable unit by its repository URL and an optional subdirectory within that repository. It is the manifest's notion of "a dependency"; a resolved version (a git tag) is paired with it elsewhere, not stored on the identity.

func ParseDependency added in v0.6.0

func ParseDependency(id string) (Dependency, error)

ParseDependency parses a dependency id of the form `repo-url` or `repo-url//subdir`, the same `//` separator imports use but without a trailing `@version`.

func (Dependency) String added in v0.6.0

func (d Dependency) String() string

String renders the dependency back to its id form, the inverse of ParseDependency.

func (Dependency) Tag added in v0.6.0

func (d Dependency) Tag(version string) string

Tag returns the git tag that names a version of this dependency: the bare version for a repo-root dependency, or `<subdir>/<version>` for a subdirectory dependency.

func (Dependency) TagPrefix added in v0.6.0

func (d Dependency) TagPrefix() string

TagPrefix returns the git tag prefix for this dependency. A subdirectory dependency uses `<subdir>/` (the monorepo convention Go submodules also follow); a repo-root dependency uses no prefix.

type Fetcher added in v0.6.0

type Fetcher interface {
	Fetch(dep Dependency, version string) (*Manifest, error)
}

Fetcher fetches a dependency's manifest at a selected version, for the version walk. It returns nil when the dependency declares no manifest: a leaf with no further dependencies, such as a Go library or a UB library that imports nothing remote.

func NewFetcher added in v0.6.0

func NewFetcher(resolver resolve.Resolver) Fetcher

NewFetcher returns a Fetcher that reads dependency manifests through resolver. It is the production Fetcher behind unobin deps; tests pass a fake resolver.

type Lock added in v0.6.0

type Lock struct {
	Version int                   `json:"version"`
	Deps    map[string]*LockedDep `json:"deps"`
}

Lock is the on-disk schema for unobin.lock. It pins the full resolved set so compiles are reproducible without re-running selection. Deps is keyed by dependency id (a repo URL with an optional `//subdir`), the same form a manifest `requires:` key uses.

func DecodeLock added in v0.6.0

func DecodeLock(b []byte) (*Lock, error)

DecodeLock parses a lock from bytes.

func LockFromImports added in v0.6.0

func LockFromImports(
	rootFS fs.FS, selection map[Dependency]string, resolver resolve.Resolver,
	replace map[Dependency]string,
) (*Lock, error)

LockFromImports builds the lock for the project rooted at rootFS. It walks every .ub file under the root -- a factory's main.ub, library bodies at the root, or libraries in subdirectories -- and through remote UB libraries their imports too. Each remote library becomes one lock entry, keyed by `repo//subdir`. Local imports are not locked and need no following: the walk already visits every file under the root, so a local library's own imports are reached directly. A library's version is its repository's selected version; a repository the selection does not cover is an error (it is imported but no floor reached it). Kind and content hash come from the fetched library subtree, so a Go library and a UB library in the same repo are recorded distinctly. A repository named in replace is read from its local path and never locked; a replaced UB library's own remote dependencies are still walked.

func NewLock added in v0.6.0

func NewLock() *Lock

NewLock returns an empty lock at the current schema version.

func ReadLock added in v0.6.0

func ReadLock(fsys fs.FS) (*Lock, error)

ReadLock reads and parses unobin.lock from fsys. A missing file returns an error wrapping fs.ErrNotExist, which callers can detect with errors.Is.

func (*Lock) RepoVersions added in v0.6.0

func (l *Lock) RepoVersions() (map[string]string, error)

RepoVersions maps each repository to its selected version, derived from the per-library entries (every library of a repo shares its version). Compile feeds this to the import walk so versionless imports resolve at the locked version.

func (*Lock) SortedIDs added in v0.6.0

func (l *Lock) SortedIDs() []string

SortedIDs returns the lock's dependency ids in sorted order.

type LockKind added in v0.6.0

type LockKind string

LockKind records how a locked dependency's integrity is guaranteed: a `ub` dependency holds a content hash of its source tree, while a `go` dependency rides the generated module's go.sum and records only a commit.

const (
	LockKindGo LockKind = "go"
	LockKindUB LockKind = "ub"
)

type LockedDep added in v0.6.0

type LockedDep struct {
	Kind    LockKind `json:"kind"`
	Version string   `json:"version"`
	Commit  string   `json:"commit"`
	Hash    string   `json:"hash,omitempty"`
}

LockedDep is one resolved dependency. Version is the selected git tag; the floor lives in the manifest and is never copied here. Hash is the source-tree content hash for `ub` dependencies and is omitted for `go`.

type Manifest added in v0.6.0

type Manifest struct {
	Requires map[Dependency]string
	Replace  map[Dependency]string
}

Manifest is a parsed unobin.manifest. Requires maps each direct dependency to the lowest version (a git tag) the factory accepts for it; resolution may select a higher one to satisfy the whole set. The factory's own version is its git tag, not recorded here. Replace maps a dependency's URL to a local path: the resolver reads that dependency from the path instead of fetching it, and the dependency needs no floor or lock entry.

func ReadManifest added in v0.6.0

func ReadManifest(fsys fs.FS) (*Manifest, error)

ReadManifest reads and parses unobin.manifest from fsys. A missing file returns an error wrapping fs.ErrNotExist, which callers can detect with errors.Is.

type Selection added in v0.6.0

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

Selection performs minimal version selection incrementally. Add records that some manifest requires a dependency at a floor version, and Selection keeps the highest floor seen for each dependency -- Go's max-of-minimums. A walker feeds it every requirement across the dependency graph; the highest floor per dependency is the selected version. Floors must be valid semver, which the manifest reader guarantees.

func NewSelection added in v0.6.0

func NewSelection() *Selection

NewSelection returns an empty Selection.

func (*Selection) Add added in v0.6.0

func (s *Selection) Add(dep Dependency, floor string) bool

Add records a required floor for dep and reports whether it raised the selected version: true the first time dep is seen, or when floor is higher than the current selection. A walker uses the result to decide whether it must read dep's manifest at the new version, since a higher version may declare different requirements.

func (*Selection) Chosen added in v0.6.0

func (s *Selection) Chosen() map[Dependency]string

Chosen returns a copy of the selected version for every dependency added so far.

func (*Selection) Version added in v0.6.0

func (s *Selection) Version(dep Dependency) string

Version returns the selected version for dep, or "" if dep has not been added.

Jump to

Keyboard shortcuts

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