Documentation
¶
Overview ¶
Package deps models a factory's dependencies. It reads manifest.ub, which lists each direct dependency and the lowest version the factory accepts for it, and drives pkg/resolve to fetch them.
Index ¶
- Constants
- func CheckNoReplacementSentinelInLock(lock *Lock) error
- func CheckPackageBoundary(src *resolve.Source, owner PackageOwner, pkg RemotePackage) error
- func CheckReplacementSentinels(manifest *Manifest) error
- func EncodeManifest(m *Manifest) []byte
- func EncodeSourceLock(lock *Lock) ([]byte, error)
- func FindManifestDir(start string) (string, error)
- func FindProjectMarkerDir(start string) (string, projectmarker.Marker, error)
- func GoReplacementSentinel(modulePath string) (string, error)
- func HasProjectMarker(fsys fs.FS) (bool, error)
- func HashUBProject(fsys fs.FS) (string, error)
- func Highest(vs []string) string
- func ImportedPackages(root string) (map[RemotePackage]bool, error)
- func ImportedRepos(root string) (map[Dependency]bool, error)
- func IsReplacementSentinel(v string) bool
- func ProjectContains(project ProjectID, pkg RemotePackage) (string, bool)
- func ProjectTag(project ProjectID, version string) string
- func ReplacementPath(replace map[Dependency]string, dep Dependency) (string, bool)
- func RequireProject(dep Dependency, version string, resolver resolve.Resolver) error
- func Resolve(root *Manifest, fetch Fetcher) (map[Dependency]string, error)
- func ResolveVersion(dep Dependency, query string, tags []string) (string, error)
- func Verify(lock *Lock, resolver resolve.Resolver) ([]string, error)
- func Versions(dep Dependency, tags []string) []string
- func WriteManifest(path string, m *Manifest) error
- func WriteSourceLock(path string, lock *Lock) error
- type Dependency
- type Fetcher
- type Lock
- type LockKind
- type LockedDep
- type Manifest
- type PackageOwner
- type ProjectID
- type RemotePackage
- type Replacement
- type Selection
Constants ¶
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.
const ManifestFileName = "manifest.ub"
ManifestFileName is the dependency manifest filename.
const ReplacementSentinel = "v0.0.0-unobin-replaced"
const SourceLockFileName = "lock.ub"
SourceLockFileName is the dependency lock filename.
Variables ¶
This section is empty.
Functions ¶
func CheckPackageBoundary ¶
func CheckPackageBoundary( src *resolve.Source, owner PackageOwner, pkg RemotePackage, ) error
func EncodeManifest ¶ added in v0.6.0
EncodeManifest renders a parseable manifest.ub draft.
func EncodeSourceLock ¶
EncodeSourceLock serializes lock as canonical lock.ub source.
func FindManifestDir ¶ added in v0.6.0
FindManifestDir walks up from start to the nearest ancestor directory holding a 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 FindProjectMarkerDir ¶
func FindProjectMarkerDir(start string) (string, projectmarker.Marker, error)
func GoReplacementSentinel ¶
func HasProjectMarker ¶
HasProjectMarker reports whether fsys contains manifest.ub or go.mod at its root.
func Highest ¶ added in v0.6.0
Highest returns the greatest version in vs by semver order, or "" when vs is empty.
func ImportedPackages ¶
func ImportedPackages(root string) (map[RemotePackage]bool, error)
ImportedPackages scans every .ub file under root and returns the set of packages named by remote imports. The version on an import is not read here: a package's version floor lives on its owning project in manifest.ub, not in the import string. Local imports are intra-project and contribute no remote package. Hidden directories (a leading dot, such as .git) are skipped.
func ImportedRepos ¶ added in v0.6.0
func ImportedRepos(root string) (map[Dependency]bool, error)
ImportedRepos is kept for callers that still need the import strings in the older Dependency form.
func IsReplacementSentinel ¶
func ProjectContains ¶
func ProjectContains(project ProjectID, pkg RemotePackage) (string, bool)
ProjectContains reports whether project owns pkg. The returned subdir is the package path inside the project, or "." when pkg names the project root.
func ProjectTag ¶
ProjectTag returns the git tag for a project version.
func ReplacementPath ¶
func ReplacementPath(replace map[Dependency]string, dep Dependency) (string, bool)
ReplacementPath returns the local replacement path for dep.
func RequireProject ¶
func RequireProject(dep Dependency, version string, resolver resolve.Resolver) error
RequireProject checks that dep resolves to a project root at version.
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
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 dependency's semver tags in increasing order.
func WriteManifest ¶ added in v0.6.0
WriteManifest serializes m as canonical manifest.ub source and atomically replaces the file at path.
func WriteSourceLock ¶
WriteSourceLock serializes lock as canonical lock.ub source and atomically replaces the file at path.
Types ¶
type Dependency ¶
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 most specific git tag that names a version of this dependency.
func (Dependency) TagPrefix ¶ added in v0.6.0
func (d Dependency) TagPrefix() string
TagPrefix returns the most specific git tag prefix for this dependency.
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
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
Lock is the on-disk schema for the dependency 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 DecodeSourceLock ¶
DecodeSourceLock parses a grammar-first lock.ub 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 -- factory.ub, library files 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). Go dependencies are recorded by project id. UB dependencies are recorded by project id with a project-root hash. 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
ReadLock reads and parses lock.ub 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
RepoVersions maps each locked dependency id to its selected version. Compile feeds this to the import walk so versionless imports resolve at the locked version.
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.
type LockedDep ¶ added in v0.6.0
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 {
UnobinVersion string
Requires map[Dependency]string
Replace map[Dependency]string
}
Manifest is a parsed dependency 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. UnobinVersion, when set, pins the toolchain: only a CLI of exactly that version compiles the project, since the unobin runtime is not a dependency whose version resolution selects.
type PackageOwner ¶
PackageOwner records the project that owns a package import.
func MostSpecificProject ¶
func MostSpecificProject(projects []ProjectID, pkg RemotePackage) (PackageOwner, bool)
MostSpecificProject chooses the project with the longest matching subdir.
type ProjectID ¶
ProjectID identifies a versioned dependency project.
func ProjectIDFromDependency ¶
func ProjectIDFromDependency(dep Dependency) ProjectID
func ProjectIDsFromDependencies ¶
func ProjectIDsFromDependencies(deps map[Dependency]string) []ProjectID
func ProjectIDsFromReplace ¶
func ProjectIDsFromReplace(replace map[Dependency]string) []ProjectID
func (ProjectID) Dependency ¶
func (p ProjectID) Dependency() Dependency
type RemotePackage ¶
RemotePackage identifies a package import below a dependency project.
func RemotePackageFromDependency ¶
func RemotePackageFromDependency(dep Dependency) RemotePackage
func (RemotePackage) Dependency ¶
func (p RemotePackage) Dependency() Dependency
func (RemotePackage) String ¶
func (p RemotePackage) String() string
type Replacement ¶
type Replacement struct {
Dep Dependency
Path string
Suffix string
Exact bool
}
Replacement describes the local path selected for a dependency.
func ReplacementFor ¶
func ReplacementFor(replace map[Dependency]string, dep Dependency) (Replacement, bool)
ReplacementFor returns the local replacement for dep. A repository-level replacement covers imports from subdirectories in that repository. A subdirectory replacement covers that subdirectory and packages below it.
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.