semanticpuppet

package module
v0.0.0-...-a87d1d1 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: BSD-3-Clause Imports: 6 Imported by: 0

Documentation

Overview

Package semanticpuppet is a pure-Go (no cgo) port of the Ruby semantic_puppet gem. It implements the two value types that Puppet uses to reason about module versions and dependency constraints:

  • Version parses and compares strings that conform to the Semantic Versioning 2.0.0 specification (https://semver.org). It exposes the MAJOR.MINOR.PATCH triple, the optional pre-release and build-metadata identifiers, SemVer precedence (build metadata is ignored), stability queries and next-version bumps.

  • VersionRange parses and evaluates the version-range grammar that semantic_puppet accepts (which follows node-semver): plain versions, the comparators <, <=, >, >=, =, hyphen ranges (1.0.0 - 2.0.0), the tilde (~, ~>, ~=) and caret (^) approximation operators, x-ranges (1.x, 1.2.x, *) and logical-or (||) unions. A range answers membership (VersionRange.Include/VersionRange.Cover) and can be intersected with another range (VersionRange.Intersection).

On top of these value types it ports the gem's module-dependency graph solver (SemanticPuppet::Dependency):

  • Source is the injectable provider seam that yields the available ModuleRelease values for a module name; AddSource/Sources/ ClearSources manage the source list as the gem's singleton does.

  • Query builds a dependency Graph for a set of top-level constraints and fetches the transitive universe of releases; Resolve walks that graph, backtracking on conflict and preferring the newest satisfying (stable-over-prerelease) release, and returns the resolved release set or an *UnsatisfiableGraph. Module- and graph-level constraints (Graph.AddConstraint/Graph.AddGraphConstraint) and dependency cycles are honoured exactly as in the gem.

The port is faithful to the observable behaviour of the gem, including its prerelease-inclusion rule: a pre-release version is only matched by a range when some clause of the range explicitly names a pre-release sharing the same MAJOR.MINOR.PATCH triple.

The package is pure Go, uses only the standard library and has no dependency on any Ruby runtime; every value type is Go-typed so that a Ruby binding layer (such as go-embedded-ruby) can marshal Ruby values onto these types.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidRange = errors.New("invalid version range")

ErrInvalidRange is returned (wrapped) by ParseRange when a string is not a valid version range. Use errors.Is to test for it.

View Source
var ErrInvalidVersion = errors.New("invalid semantic version")

ErrInvalidVersion is returned (wrapped) by Parse when a string is not a valid Semantic Version. Use errors.Is to test for it.

Functions

func AddSource

func AddSource(s Source)

AddSource appends a source to the list, mirroring Dependency.add_source.

func ClearSources

func ClearSources()

ClearSources empties the source list, mirroring Dependency.clear_sources.

func IsValid

func IsValid(ver string) bool

IsValid reports whether ver is a valid Semantic Version string.

func SortVersions

func SortVersions(versions []*Version)

SortVersions sorts versions in ascending SemVer precedence order, in place.

func Unsatisfiable

func Unsatisfiable() string

Unsatisfiable returns the module that the most recent Resolve failure could not satisfy, or "" if there was none. It mirrors Dependency.unsatisfiable.

Types

type BaseSource

type BaseSource struct{}

BaseSource can be embedded in a Source implementation to inherit the gem's default priority of 0.

func (BaseSource) Priority

func (BaseSource) Priority() int

Priority returns 0, the default source priority.

type ByVersion

type ByVersion []*Version

ByVersion attaches sort.Interface to a slice of versions, ordering them by ascending SemVer precedence.

func (ByVersion) Len

func (s ByVersion) Len() int

func (ByVersion) Less

func (s ByVersion) Less(i, j int) bool

func (ByVersion) Swap

func (s ByVersion) Swap(i, j int)

type Graph

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

Graph is the root of a dependency query: the set of top-level module constraints plus any additional module- or graph-level constraints. It mirrors SemanticPuppet::Dependency::Graph. Build one with Query.

func Query

func Query(modules map[string]string) (*Graph, error)

Query builds a dependency Graph for the given top-level module ranges and eagerly fetches the transitive universe of releases from the configured sources. It mirrors Dependency.query. It returns an error wrapping ErrInvalidRange if any range string is malformed.

func (*Graph) Add

func (g *Graph) Add(nodes ...*ModuleRelease)

Add records the given releases against any matching dependency, keeping each dependency's release list sorted. It mirrors GraphNode#<<.

func (*Graph) AddConstraint

func (g *Graph) AddConstraint(source, mod, desc string, test func(*ModuleRelease) bool)

AddConstraint adds a module-level constraint: releases of mod must satisfy test. desc describes the constraint and source names its origin. It mirrors GraphNode#add_constraint as exposed on the graph.

func (*Graph) AddGraphConstraint

func (g *Graph) AddGraphConstraint(source string, test func([]*ModuleRelease) bool)

AddGraphConstraint adds a whole-solution constraint: every candidate solution (partial or complete) must satisfy test. It mirrors Graph#add_graph_constraint.

func (*Graph) Children

func (g *Graph) Children() map[string]*ModuleRelease

Children returns the resolved child nodes populated by [PopulateChildren]. It mirrors GraphNode#children.

func (*Graph) Dependencies

func (g *Graph) Dependencies() map[string][]*ModuleRelease

Dependencies returns the map of dependency name to the satisfying releases discovered for it. It mirrors GraphNode#dependencies.

func (*Graph) DependencyNames

func (g *Graph) DependencyNames() []string

DependencyNames returns the dependency names in registration order. It mirrors GraphNode#dependency_names.

func (*Graph) Modules

func (g *Graph) Modules() []string

Modules returns the top-level module names of the query. It mirrors Graph#modules.

func (*Graph) PopulateChildren

func (g *Graph) PopulateChildren(nodes []*ModuleRelease)

PopulateChildren walks a resolved solution and records, for each satisfied dependency, the release that satisfies it, recursing across the solution. It mirrors GraphNode#populate_children.

func (*Graph) Satisfied

func (g *Graph) Satisfied() bool

Satisfied reports whether every registered dependency has at least one satisfying release. It mirrors GraphNode#satisfied?.

func (*Graph) SatisfiesConstraints

func (g *Graph) SatisfiesConstraints(rel *ModuleRelease) bool

SatisfiesConstraints reports whether rel passes every constraint recorded for rel's module name. It mirrors GraphNode#satisfies_constraints?.

func (*Graph) SatisfiesDependency

func (g *Graph) SatisfiesDependency(rel *ModuleRelease) bool

SatisfiesDependency reports whether rel is a satisfying release for one of this node's dependencies. It mirrors GraphNode#satisfies_dependency?.

func (*Graph) SatisfiesGraph

func (g *Graph) SatisfiesGraph(solution []*ModuleRelease) bool

SatisfiesGraph reports whether solution violates no graph-level constraint. It mirrors Graph#satisfies_graph?.

type ModuleRelease

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

ModuleRelease is one published release of a module: a name, a Version and a set of dependency constraints. It mirrors SemanticPuppet::Dependency::ModuleRelease.

func CreateRelease

func CreateRelease(src Source, name, version string, deps map[string]string) (*ModuleRelease, error)

CreateRelease builds a ModuleRelease belonging to src, mirroring Source#create_release. version is a Semantic Version string; deps maps a dependency name to a version-range string (an empty string is treated as ">= 0.0.0", matching the gem's nil handling). It returns an error wrapping ErrInvalidVersion or ErrInvalidRange for malformed input.

func FetchReleases

func FetchReleases(name string) []*ModuleRelease

FetchReleases returns every distinct release available for name across all sources (first source to offer a given version wins). It mirrors Dependency.fetch_releases.

func NewModuleRelease

func NewModuleRelease(src Source, name string, version *Version, deps map[string]*VersionRange) *ModuleRelease

NewModuleRelease constructs a release owned by src with the given name, version and dependency ranges. It mirrors ModuleRelease#initialize: each dependency becomes both a registered dependency and a constraint requiring the dependency's version to fall within range.

func Resolve

func Resolve(graph *Graph) ([]*ModuleRelease, error)

Resolve resolves graph into a flat list of releases satisfying every transitive dependency and constraint, preferring the newest satisfying (stable-over-prerelease) release and backtracking on conflict. It mirrors Dependency.resolve. On failure it returns an *UnsatisfiableGraph.

func (*ModuleRelease) Add

func (g *ModuleRelease) Add(nodes ...*ModuleRelease)

Add records the given releases against any matching dependency, keeping each dependency's release list sorted. It mirrors GraphNode#<<.

func (*ModuleRelease) Children

func (g *ModuleRelease) Children() map[string]*ModuleRelease

Children returns the resolved child nodes populated by [PopulateChildren]. It mirrors GraphNode#children.

func (*ModuleRelease) Compare

func (m *ModuleRelease) Compare(o *ModuleRelease) int

Compare orders releases by [priority, name, version], mirroring ModuleRelease#<=>.

func (*ModuleRelease) Dependencies

func (g *ModuleRelease) Dependencies() map[string][]*ModuleRelease

Dependencies returns the map of dependency name to the satisfying releases discovered for it. It mirrors GraphNode#dependencies.

func (*ModuleRelease) DependencyNames

func (g *ModuleRelease) DependencyNames() []string

DependencyNames returns the dependency names in registration order. It mirrors GraphNode#dependency_names.

func (*ModuleRelease) Eql

func (m *ModuleRelease) Eql(o *ModuleRelease) bool

Eql reports whether two releases are equal by name, version and dependency set, mirroring ModuleRelease#eql?/#==. A nil operand is never equal.

func (*ModuleRelease) Name

func (m *ModuleRelease) Name() string

Name returns the module name.

func (*ModuleRelease) PopulateChildren

func (g *ModuleRelease) PopulateChildren(nodes []*ModuleRelease)

PopulateChildren walks a resolved solution and records, for each satisfied dependency, the release that satisfies it, recursing across the solution. It mirrors GraphNode#populate_children.

func (*ModuleRelease) Satisfied

func (g *ModuleRelease) Satisfied() bool

Satisfied reports whether every registered dependency has at least one satisfying release. It mirrors GraphNode#satisfied?.

func (*ModuleRelease) SatisfiesConstraints

func (g *ModuleRelease) SatisfiesConstraints(rel *ModuleRelease) bool

SatisfiesConstraints reports whether rel passes every constraint recorded for rel's module name. It mirrors GraphNode#satisfies_constraints?.

func (*ModuleRelease) SatisfiesDependency

func (g *ModuleRelease) SatisfiesDependency(rel *ModuleRelease) bool

SatisfiesDependency reports whether rel is a satisfying release for one of this node's dependencies. It mirrors GraphNode#satisfies_dependency?.

func (*ModuleRelease) String

func (m *ModuleRelease) String() string

String renders the release for diagnostics, mirroring ModuleRelease#to_s.

func (*ModuleRelease) Version

func (m *ModuleRelease) Version() *Version

Version returns the release's version.

type ParseError

type ParseError struct {
	// Kind is "version" or "range".
	Kind string
	// Input is the offending string.
	Input string
	// contains filtered or unexported fields
}

ParseError describes a failure to parse a version or version range. It wraps either ErrInvalidVersion or ErrInvalidRange.

func (*ParseError) Error

func (e *ParseError) Error() string

func (*ParseError) Unwrap

func (e *ParseError) Unwrap() error

Unwrap returns the sentinel error (ErrInvalidVersion or ErrInvalidRange).

type Source

type Source interface {
	// Priority orders sources when the same version is offered by more than
	// one of them; a release's priority participates in release ordering.
	Priority() int
	// Fetch returns the releases the source knows about for name (possibly
	// empty). It must not return nil-typed elements.
	Fetch(name string) []*ModuleRelease
}

Source is the provider seam of the resolver. Given a module name it yields every release it knows about for that name. Implementations are injected via AddSource; the resolver never performs any I/O of its own, so tests can supply a fixed universe of releases.

It mirrors SemanticPuppet::Dependency::Source. The base gem class also has a default priority of 0 and a create_release helper; BaseSource provides the former and CreateRelease the latter.

func Sources

func Sources() []Source

Sources returns a copy of the current source list, mirroring Dependency.sources (which returns a frozen copy).

type UnsatisfiableGraph

type UnsatisfiableGraph struct {
	// Modules is the list of top-level module names of the graph.
	Modules []string
	// Unsatisfied is the module that could not be satisfied, or "" when the
	// resolver could not attribute the failure to a single module.
	Unsatisfied string
	// contains filtered or unexported fields
}

UnsatisfiableGraph is returned by Resolve when no consistent set of releases satisfies the graph. It mirrors SemanticPuppet::Dependency::UnsatisfiableGraph.

func (*UnsatisfiableGraph) Error

func (e *UnsatisfiableGraph) Error() string

Error returns the human-readable failure message.

type Version

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

Version is an immutable Semantic Version 2.0.0 value. The zero value is not usable; construct one with Parse.

func MaxVersion

func MaxVersion(versions ...*Version) *Version

MaxVersion returns the highest-precedence version among versions, or nil if no versions are supplied.

func MinVersion

func MinVersion(versions ...*Version) *Version

MinVersion returns the lowest-precedence version among versions, or nil if no versions are supplied.

func MustParse

func MustParse(ver string) *Version

MustParse is like Parse but panics if ver is not a valid version. It is intended for use with constant version strings.

func Parse

func Parse(ver string) (*Version, error)

Parse parses ver as a Semantic Version 2.0.0 string of the form MAJOR.MINOR.PATCH, optionally followed by a "-prerelease" and/or a "+build" section. It returns an error wrapping ErrInvalidVersion for malformed input, including numeric pre-release identifiers with leading zeroes.

func (*Version) Build

func (v *Version) Build() string

Build returns the build-metadata identifier without its leading '+', or the empty string if there is no build metadata.

func (*Version) Compare

func (v *Version) Compare(other *Version) int

Compare compares v and other by SemVer precedence, returning -1, 0 or +1. Build metadata is ignored, as required by the specification.

func (*Version) Equal

func (v *Version) Equal(other *Version) bool

Equal reports whether v and other are identical, including pre-release and build metadata (an absent pre-release differs from an empty one).

func (*Version) Major

func (v *Version) Major() int

Major returns the major component.

func (*Version) Minor

func (v *Version) Minor() int

Minor returns the minor component.

func (*Version) NextMajor

func (v *Version) NextMajor() *Version

NextMajor returns MAJOR+1.0.0.

func (*Version) NextMinor

func (v *Version) NextMinor() *Version

NextMinor returns MAJOR.MINOR+1.0.

func (*Version) NextPatch

func (v *Version) NextPatch() *Version

NextPatch returns MAJOR.MINOR.PATCH+1.

func (*Version) Patch

func (v *Version) Patch() int

Patch returns the patch component.

func (*Version) Prerelease

func (v *Version) Prerelease() string

Prerelease returns the pre-release identifier without its leading '-', or the empty string if there is no pre-release.

func (*Version) Stable

func (v *Version) Stable() bool

Stable reports whether this is a stable release, i.e. it carries no pre-release identifier.

func (*Version) String

func (v *Version) String() string

String returns the canonical string representation of the version.

func (*Version) ToStable

func (v *Version) ToStable() *Version

ToStable returns this version stripped of any pre-release identifier. Build metadata is preserved. If the version is already stable it is returned unchanged.

type VersionRange

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

VersionRange is an immutable set of versions expressed as a union of comparator clauses. Construct one with ParseRange.

func MustParseRange

func MustParseRange(rangeString string) *VersionRange

MustParseRange is like ParseRange but panics on error. It is intended for use with constant range strings.

func ParseRange

func ParseRange(rangeString string) (*VersionRange, error)

ParseRange parses a version-range string. It accepts plain versions ("1.2.3"), the comparators <, <=, >, >=, =, hyphen ranges ("1.0.0 - 2.0.0"), the tilde (~, ~>, ~=) and caret (^) operators, x-ranges ("1.x", "1.2.x", "*") and logical-or unions ("... || ..."). An empty string matches every version. It returns an error wrapping ErrInvalidRange for malformed input.

func (*VersionRange) Cover

func (r *VersionRange) Cover(version *Version) bool

Cover is an alias for VersionRange.Include.

func (*VersionRange) Equal

func (r *VersionRange) Equal(other *VersionRange) bool

Equal reports whether r and other consist of the same matcher clauses.

func (*VersionRange) Include

func (r *VersionRange) Include(version *Version) bool

Include reports whether version is a member of the range. A pre-release version is only matched when a clause of the range explicitly names a pre-release sharing the same major.minor.patch triple.

func (*VersionRange) Inspect

func (r *VersionRange) Inspect() string

Inspect returns the canonical representation of the range assembled from its matcher clauses, independent of how it was originally written.

func (*VersionRange) Intersection

func (r *VersionRange) Intersection(other *VersionRange) *VersionRange

Intersection returns the range covering exactly the versions matched by both r and other. If the ranges do not overlap, an empty range is returned.

func (*VersionRange) Max

func (r *VersionRange) Max() *Version

Max returns the version that ends the range, or nil if the range is a union of more than one disjoint clause.

func (*VersionRange) Min

func (r *VersionRange) Min() *Version

Min returns the version that begins the range, or nil if the range is a union of more than one disjoint clause.

func (*VersionRange) String

func (r *VersionRange) String() string

String returns the string the range was parsed from, or the canonical inspect form for ranges produced by intersection.

Jump to

Keyboard shortcuts

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