Documentation
¶
Overview ¶
Package deps models a factory's dependencies. It reads project.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 CheckNoReplacementSentinelInProjectLock(projectLock *ProjectLock) error
- func CheckPackageBoundary(src *resolve.Source, owner PackageOwner, pkg RemotePackage) error
- func CheckReplacementSentinels(project *Project) error
- func EncodeProject(m *Project) []byte
- func EncodeProjectLock(projectLock *ProjectLock) ([]byte, error)
- func FindProjectDir(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 *Project, fetch Fetcher) (map[Dependency]string, error)
- func ResolveVersion(dep Dependency, query string, tags []string) (string, error)
- func Verify(projectLock *ProjectLock, resolver resolve.Resolver) ([]string, error)
- func Versions(dep Dependency, tags []string) []string
- func WriteProject(path string, m *Project) error
- func WriteProjectLock(path string, projectLock *ProjectLock) error
- type Dependency
- type Fetcher
- type PackageOwner
- type Project
- type ProjectID
- type ProjectLock
- type ProjectLockDep
- type ProjectLockKind
- type RemotePackage
- type Replacement
- type Requirement
- type Selection
Constants ¶
const CurrentProjectLockVersion = 1
CurrentProjectLockVersion is the schema version this package reads and writes. A different version errors on read, since this build cannot guarantee a correct interpretation.
const ProjectFileName = "project.ub"
ProjectFileName is the dependency project filename.
const ProjectLockFileName = "project-lock.ub"
ProjectLockFileName is the dependency project-lock filename.
const ReplacementSentinel = "v0.0.0-unobin-replaced"
Variables ¶
This section is empty.
Functions ¶
func CheckNoReplacementSentinelInProjectLock ¶
func CheckNoReplacementSentinelInProjectLock(projectLock *ProjectLock) error
func CheckPackageBoundary ¶
func CheckPackageBoundary( src *resolve.Source, owner PackageOwner, pkg RemotePackage, ) error
func EncodeProject ¶
EncodeProject renders a parseable project.ub draft.
func EncodeProjectLock ¶
func EncodeProjectLock(projectLock *ProjectLock) ([]byte, error)
EncodeProjectLock serializes projectLock as canonical project-lock.ub source.
func FindProjectDir ¶
FindProjectDir walks up from start to the nearest ancestor directory holding a project 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 project is found.
func FindProjectMarkerDir ¶
func FindProjectMarkerDir(start string) (string, projectmarker.Marker, error)
func GoReplacementSentinel ¶
func HasProjectMarker ¶
HasProjectMarker reports whether fsys contains project.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 project.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 *Project, fetch Fetcher) (map[Dependency]string, error)
Resolve runs minimal version selection over the dependency graph rooted at a project. 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 project. The result maps each dependency to its selected version -- project-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(projectLock *ProjectLock, resolver resolve.Resolver) ([]string, error)
Verify re-fetches every ub-kind dependency in project-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 WriteProject ¶
WriteProject serializes m as canonical project.ub source and atomically replaces the file at path.
func WriteProjectLock ¶
func WriteProjectLock(path string, projectLock *ProjectLock) error
WriteProjectLock serializes projectLock as canonical project-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 project'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) (*Project, error)
}
Fetcher fetches a dependency's project at a selected version, for the version walk. It returns nil when the dependency declares no project: 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 projects through resolver. It is the production Fetcher behind unobin deps; tests pass a fake resolver.
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 Project ¶
type Project struct {
UnobinVersion string
Requires map[Dependency]Requirement
Replace map[Dependency]string
}
Project is a parsed dependency project. Requires maps each 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 project-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.
func ReadProject ¶
ReadProject reads and parses project.ub from fsys. A missing file returns an error wrapping fs.ErrNotExist, which callers can detect with errors.Is.
func (*Project) DirectCount ¶
func (*Project) DirectRequireVersions ¶
func (m *Project) DirectRequireVersions() map[Dependency]string
func (*Project) IndirectCount ¶
func (*Project) RequireVersions ¶
func (m *Project) RequireVersions() map[Dependency]string
func (*Project) SetRequire ¶
func (m *Project) SetRequire(dep Dependency, version string, indirect bool)
type ProjectID ¶
ProjectID identifies a versioned dependency project.
func ProjectIDFromDependency ¶
func ProjectIDFromDependency(dep Dependency) ProjectID
func ProjectIDsFromDependencies ¶
func ProjectIDsFromDependencies[V any](deps map[Dependency]V) []ProjectID
func ProjectIDsFromReplace ¶
func ProjectIDsFromReplace(replace map[Dependency]string) []ProjectID
func (ProjectID) Dependency ¶
func (p ProjectID) Dependency() Dependency
type ProjectLock ¶
type ProjectLock struct {
Version int
ToolchainVersion string
Deps map[string]*ProjectLockDep
}
ProjectLock is the on-disk schema for the dependency project-lock file. It pins the full resolved set so compiles are reproducible without re-running selection. Deps is keyed by dependency id, a repository URL with an optional `//subdir`, the same form a project `requires:` key uses.
func DecodeProjectLock ¶
func DecodeProjectLock(b []byte) (*ProjectLock, error)
DecodeProjectLock parses a grammar-first project-lock.ub from bytes.
func NewProjectLock ¶
func NewProjectLock() *ProjectLock
NewProjectLock returns an empty project-lock at the current schema version.
func ProjectLockFromImports ¶
func ProjectLockFromImports( rootFS fs.FS, selection map[Dependency]string, resolver resolve.Resolver, replace map[Dependency]string, ) (*ProjectLock, error)
ProjectLockFromImports builds the project-lock for the project rooted at rootFS. It visits every .ub file under the root -- factory.ub, library files at the root, or libraries in subdirectories -- and visits remote UB library imports too. Each remote library becomes one selected dependency entry, keyed by `repo//subdir`. Local imports are not selected separately because the project visit already sees every file under the root. A library's version is its repository's selected version; a repository the selection does not cover is an error. 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 added to the project-lock; a replaced UB library's own remote dependencies are still visited.
func ReadProjectLock ¶
func ReadProjectLock(fsys fs.FS) (*ProjectLock, error)
ReadProjectLock reads and parses project-lock.ub from fsys. A missing file returns an error wrapping fs.ErrNotExist, which callers can detect with errors.Is.
func (*ProjectLock) RepoVersions ¶
func (l *ProjectLock) RepoVersions() (map[string]string, error)
RepoVersions maps each selected dependency id to its selected version. Compile feeds this to the import walk so versionless imports resolve at the selected version.
func (*ProjectLock) SortedIDs ¶
func (l *ProjectLock) SortedIDs() []string
SortedIDs returns the dependency ids in sorted order.
type ProjectLockDep ¶
type ProjectLockDep struct {
Kind ProjectLockKind
Version string
Commit string
Hash string
}
ProjectLockDep is one resolved dependency. Version is the selected git tag; the floor lives in project.ub and is never copied here. Hash is the source-tree content hash for `ub` dependencies and is omitted for `go`.
type ProjectLockKind ¶
type ProjectLockKind string
ProjectLockKind records how a selected 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 ( ProjectLockKindGo ProjectLockKind = "go" ProjectLockKindUB ProjectLockKind = "ub" )
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 Requirement ¶
Requirement is a root dependency floor declared by project.ub.
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 project 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 project 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 project 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.