pakr

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

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

Go to latest
Published: Dec 14, 2016 License: MIT Imports: 10 Imported by: 0

README

pakr

A package version resolver library, built on top of bindings for picosat

GoDoc

pakr (package resolver) provides a way to generically define both an index of total available packages, and a list of requirements/selections from that index, and resolve a package solution if possible.

  • A "product" is a unique name that will have 1 or more package versions.

  • A "package" is a specific version of a product, with specific dependencies.

Examples

P := NewPackage
index := []Dependency{
    {
        P("A", "1.0.0"), []Packages{
            {P("C", "1.0.0")},
        },
    },
    {
        P("B", "1.0.0"), []Packages{
            {P("C", "2.0.0")},
        },
    },
}

required := Packages{
    P("A", "1.0.0"),
    P("B", "1.0.0")}

// Just set our specific requires to be each Package defined
// in the Dependency index
resolver := NewResolver(required, index)

solved, err := resolver.Resolve()
if err != nil {
    panic(err.Error())
}
if solved {
    panic("Resolver was expected to fail, but succeeded.")
}

fmt.Println("The following requirements cannot be satisfied:")
for _, c := range resolver.Conflicts() {
    fmt.Printf("    %s\n", c.PackageName())
}

fmt.Println("\nDetails:")
detailed, _ := resolver.DetailedConflicts()
fmt.Println(detailed)

Output:

The following requirements cannot be satisfied:
    A-1.0.0
    B-1.0.0

Details:
Package A-1.0.0 depends on one of (C-1.0.0)
Package B-1.0.0 depends on one of (C-2.0.0)
Package C-2.0.0 conflicts with (C-1.0.0)

Documentation

Overview

pakr (package resolver) provides a way to generically define both an index of total available packages, and a list of requirements/selections from that index, and resolve a package solution if possible.

- A "product" is a unique name that will have 1 or more package versions.

- A "package" is a specific version of a product, with specific dependencies.

Example (Conflict)
P := NewPackage

// Define an index that represents all available Packages
// and their dependencies
index := []Dependency{
	{
		P("A", "1.0.0"), []Packages{
			{P("C", "1.0.0")},
		},
	},
	{
		P("B", "1.0.0"), []Packages{
			{P("C", "2.0.0")},
		},
	},
}

// Our specific constraints that we want to solve
required := Packages{
	P("A", "1.0.0"),
	P("B", "1.0.0")}

// Just set our specific requires to be each Package defined
// in the Dependency index
resolver := NewResolver(required, index)

solved, err := resolver.Resolve()
if err != nil {
	panic(err.Error())
}
if solved {
	panic("Resolver was expected to fail, but succeeded.")
}

fmt.Println("The following requirements cannot be satisfied:")
for _, c := range resolver.Conflicts() {
	fmt.Printf("    %s\n", c.PackageName())
}

fmt.Println("\nDetails:")
detailed, _ := resolver.DetailedConflicts()
fmt.Println(detailed)
Output:

The following requirements cannot be satisfied:
    A-1.0.0
    B-1.0.0

Details:
Package A-1.0.0 depends on one of (C-1.0.0)
Package B-1.0.0 depends on one of (C-2.0.0)
Package C-2.0.0 conflicts with (C-1.0.0)
Example (Solve)
P := NewPackage

// Define an index that represents all available Packages
// and their dependencies
index := []Dependency{
	{
		P("A", "1.0.0"), []Packages{
			{P("B", "1.0.0")},
		},
	},
	{
		P("A", "2.0.0"), []Packages{
			{P("B", "2.0.0")},
		},
	},
	{
		P("B", "2.0.0"), []Packages{
			{P("C", "1.0.0")},
		},
	},
}

// Our specific constraints that we want to solve
required := Packages{P("A", "2.0.0")}

// Just set our specific requires to be each Package defined
// in the Dependency index
resolver := NewResolver(required, index)

solved, err := resolver.Resolve()
if err != nil {
	panic(err.Error())
}
if !solved {
	panic("Resolver was expected to succeed, but failed.")
}

solutions := resolver.Solution()
sort.Sort(solutions)

for _, pkg := range solutions {
	fmt.Println(pkg.PackageName())
}
Output:

A-2.0.0
B-2.0.0
C-1.0.0

Index

Examples

Constants

View Source
const (
	// Leave the package index in its original order
	ResolveSortNone resolveSort = iota
	// Sort packages to prefer lower versions first
	ResolveSortLow
	// Sort packages to prefer higher versions first
	ResolveSortHigh
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Dependency

type Dependency struct {
	Target   Packager
	Requires []Packages
}

Defines a Package, and all of its direct dependencies. Dependencies are lists of expanded Package version ranges. So for each package that is a dependency, all allowable Package versions are listed.

func NewDependency

func NewDependency(p Packager) *Dependency

Return a new Dependencies instance, with a Packager and an empty list of Version sets

func (*Dependency) AddVersionSet

func (p *Dependency) AddVersionSet(vers Packages)

AddVersionSet appends a list of Package version of a Product, to the Depends list.

type Package

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

A Package is a specific version of a Product

func NewPackage

func NewPackage(productName, version string) *Package

NewPackage creates a new Package with a product name and version

func (*Package) PackageName

func (p *Package) PackageName() string

PackageName returns the <Name>-<Version> of the Package

func (*Package) ProductName

func (p *Package) ProductName() string

ProductName returns the unversioned name of the product

func (*Package) String

func (p *Package) String() string

String returns the string name of the Package

func (*Package) Version

func (p *Package) Version() string

Version returns the version identifier

type PackageRelation

type PackageRelation struct {
	Packages Packages
	Relates  Relation
}

PackageRelation relationship of either one Package to the overall requirements, or two packages to eachother

func (*PackageRelation) String

func (r *PackageRelation) String() string

Generate the string representation of the relationship as a descriptive phrase.

type PackageRelations

type PackageRelations []*PackageRelation

PackageRelations is a list of PackageRelation objects

func (PackageRelations) String

func (p PackageRelations) String() string

Generate all descriptive phrases for contained relationships, separated by newlines

type Packager

type Packager interface {
	ProductName() string
	PackageName() string
	Version() string
}

Packager interface represents an object that defines its Product name, Package name, and version identifier. Packages are variants of the same Product, with a different version number. A Product has 1 or more Packages, defining different versions.

type Packages

type Packages []Packager

A slice of Packagers that supports sorting

func (Packages) Len

func (p Packages) Len() int

Len returns the number of Package objects contained

func (Packages) Less

func (p Packages) Less(i, j int) bool

Less compares to indexes of a Packages instance

func (Packages) String

func (p Packages) String() string

func (Packages) Swap

func (p Packages) Swap(i, j int)

Swaps two indices of a Packages instance

type ProductMap

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

A struct that tracks mappings of Product names to package sets, and Package names to Packagers. Create with NewProductMap()

func NewProductMap

func NewProductMap() *ProductMap

ProductMap tracks Packages, organizing them as a mapping of Product names to sets of Packages (version of each Product)

func (*ProductMap) Add

func (m *ProductMap) Add(p Packager)

Add a Package to the mapping It will be organized by its Product name

func (*ProductMap) NumPackages

func (m *ProductMap) NumPackages() int

Return the number of tracked packages

func (*ProductMap) NumProducts

func (m *ProductMap) NumProducts() int

Return the number of tracked products

func (*ProductMap) PackageByName

func (m *ProductMap) PackageByName(packageName string) (Packager, error)

Looks up and returns a Package by its PackageName Returns a non-nil error if not found

func (*ProductMap) Packages

func (m *ProductMap) Packages(productName string) []Packager

Retrieve all Packages mapped by their Product name

type Relation

type Relation string

A constant defining a relationship of a Packages contribution to a set of requirements

const (
	Required  Relation = `Required`
	Conflicts Relation = `Conflicts`
	Depends   Relation = `Depends`
	Restricts Relation = `Restricted`
)

type Resolver

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

A Resolver attempts to solve a package solution from a given set of constraints and assumptions for a package index list

func NewResolver

func NewResolver(requires Packages, index []Dependency) *Resolver

NewResolver creates a new Resolver, from a given package dependency list

func NewSortResolver

func NewSortResolver(requires Packages, index []Dependency, sortMode resolveSort) *Resolver

NewSortResolver creates a new Resolver, from a given package dependency list. Specify a sort order operation to apply to the packages when intializing the index. Sort order affects the preference in choosing higher vs lower version packages in the solution.

func (*Resolver) Conflicts

func (r *Resolver) Conflicts() Packages

Returns a package list of all Packages that were requirements, or added with RequireTemp(), that caused the Resolver to fail. Only makes sense to call this after having called Resolve() and finding that the resolve was not successful.

func (*Resolver) DetailedConflicts

func (r *Resolver) DetailedConflicts() (PackageRelations, error)

If the previous call to Resolve() returned false, meaning the currently requirements are no solvable, then this method builds a list of the packages involved in the conflict.

Returns a slice of PackageRelations, which describe 1 or 2 packages, and a descriptive Relation flag

func (*Resolver) Initialize

func (r *Resolver) Initialize() error

Resets all internal state, and initializes based on the currently set package dependency requirements This gets called automatically when calling SetRequirements()

func (*Resolver) IsPackageConflict

func (r *Resolver) IsPackageConflict(p Packager) bool

Return true if a given required Package caused the Resolver to fail. Only makes sense to call this after having called Resolve() and finding that the resolve was not successful.

func (*Resolver) IsPackageNameConflict

func (r *Resolver) IsPackageNameConflict(packageName string) bool

Return true if a given required package (by name) caused the Resolver to fail. Only makes sense to call this after having called Resolve() and finding that the resolve was not successful.

func (*Resolver) PackageByName

func (r *Resolver) PackageByName(packageName string) (Packager, error)

Return a Package by its name. If the Package is not known to the Resolver, return an error

func (*Resolver) RequireTemp

func (r *Resolver) RequireTemp(p Packager)

Add a package as a requirement that must be satisfied by the solver. This addition is only valid until the next call to Resolve(), after which it will be removed.

func (*Resolver) Resolve

func (r *Resolver) Resolve() (bool, error)

Attempt to resolve a package solution with the currently set criteria. Returns a bool indicating whether the Resolver succeeded or conflicted. Returns a non-nil error if there was an internal error.

func (*Resolver) SetPackageIndex

func (r *Resolver) SetPackageIndex(index []Dependency)

Set the package dependency list. Resets the internal solver and state.

func (*Resolver) SetRequirements

func (r *Resolver) SetRequirements(requires Packages)

Set the package dependency list. Resets the internal solver and state.

func (*Resolver) Solution

func (r *Resolver) Solution() Packages

Returns the last successfully resolved solution of packages

func (*Resolver) Solved

func (r *Resolver) Solved() bool

Returns the returned by the last call to Resolve(), indicating whether the current requirements are solved or not.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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