libeopkg

package
v0.0.0-...-eb887e7 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2024 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package libeopkg provides Go-native access to `.eopkg` files, allowing ferryd to read and manipulate them without having a host-side eopkg tool.

It should also be noted that `eopkg` is implemented in Python, so calling out to the host-side tool just isn't acceptable for the performance we require. In time, `sol` will replace eopkg and it is very likely that we'll base the new `libsol` component on the C library using cgo.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMismatchedDelta is returned when the input packages should never be delta'd,
	// i.e. they're unrelated
	ErrMismatchedDelta = errors.New("Delta is not possible between the input packages")

	// ErrDeltaPointless is returned when it is quite literally pointless to bother making
	// a delta package, due to the packages having exactly the same content.
	ErrDeltaPointless = errors.New("File set is the same, no point in creating delta")
)
View Source
var (
	// ErrNotYetImplemented is a placeholder during development
	ErrNotYetImplemented = errors.New("Not yet implemented")

	// ErrEopkgCorrupted is provided when a file does not conform to eopkg spec
	ErrEopkgCorrupted = errors.New(".eopkg file is corrupted or invalid")
)

Functions

func ComputeDeltaName

func ComputeDeltaName(oldPackage, newPackage *MetaPackage) string

ComputeDeltaName will determine the target name for the delta eopkg

func FixMissingLocalLanguage

func FixMissingLocalLanguage(fields *[]LocalisedField)

FixMissingLocalLanguage should be used on a set of LocalisedField to restore the missing "en" that is required in the very first field set.

func IsDeltaPossible

func IsDeltaPossible(oldPackage, newPackage *MetaPackage) bool

IsDeltaPossible will compare the two input packages and determine if it is possible for a delta to be considered. Note that we do not compare the distribution _name_ because Solus already had to do a rename once, and that broke delta updates. Let's not do that again. eopkg should in reality determine delta applicability based on repo origin + upgrade path, not names

func UnxzFile

func UnxzFile(inputPath string, keepOriginal bool) error

UnxzFile will decompress the input XZ file and leave a new file in place without the .xz suffix

func UnzstdFile

func UnzstdFile(inputPath string, keepOriginal bool) error

UnzstdFile will decompress the input zstd file and leave a new file in place without the .zst suffix

func XzFile

func XzFile(inputPath string, keepOriginal bool) error

XzFile is a simple wrapper around the xz utility to compress the input file. This will be performed in place and leave a ".xz" suffixed file in place Keep original determines whether we'll keep the original file

func ZstdFile

func ZstdFile(inputPath string, keepOriginal bool) error

ZstdFile is a simple wrapper around the zstd utility to compress the input file. This will be performed in place and leave a ".zst" suffixed file in place Keep original determines whether we'll keep the original file

Types

type Action

type Action struct {
	Value   string `xml:",chardata"`              // i.e. "systemRestart
	Package string `xml:"package,attr,omitempty"` // i.e. package="kernel"
}

Action represents an action to take upon applying an update, such as restarting the system.

type COMAR

type COMAR struct {
	Value  string `xml:",chardata"`             // Value of the COMAR name
	Script string `xml:"script,attr,omitempty"` // The type of script
}

A COMAR script

type Component

type Component struct {
	Name string // ID of this component, i.e. "system.base"

	// Translated short name
	LocalName []LocalisedField

	// Translated summary
	Summary []LocalisedField

	// Translated description
	Description []LocalisedField

	Group      string // Which group this component belongs to
	Maintainer struct {
		Name  string // Name of the component maintainer
		Email string // Contact e-mail address of component maintainer
	}
}

A Component as seen through the eyes of XML

type ComponentSort

type ComponentSort []Component

ComponentSort allows us to quickly sort our components by name

func (ComponentSort) Len

func (g ComponentSort) Len() int

func (ComponentSort) Less

func (g ComponentSort) Less(a, b int) bool

func (ComponentSort) Swap

func (g ComponentSort) Swap(a, b int)

type Components

type Components struct {
	Components []Component `xml:"Components>Component"`
}

Components is a simple helper wrapper for loading from components.xml files

func NewComponents

func NewComponents(xmlfile string) (*Components, error)

NewComponents will load the Components data from the XML file

type Delta

type Delta struct {
	ReleaseFrom int    `xml:"releaseFrom,attr,omitempty"` // Delta from specified release to this one
	PackageURI  string // Relative location to the package
	PackageSize int64  // Actual size on disk of the .eopkg
	PackageHash string // Sha1sum for this package
}

Delta describes a delta package that may be used for an update to save on bandwidth for the users.

Delta upgrades are determined by placing the <DeltaPackages> section into the index, with each Delta listed with a releaseFrom. If the user is currently using one of the listed releaseFrom IDs in their installation, that delta package will be selected instead of the full package.

type DeltaProducer

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

DeltaProducer is responsible for taking two eopkg packages and spitting out a delta package for them, containing only the new files.

func NewDeltaProducer

func NewDeltaProducer(baseDir string, pkgOld string, pkgNew string) (*DeltaProducer, error)

NewDeltaProducer will return a new delta producer for the given input packages It is very important that the old and new packages are in the correct order!

func (*DeltaProducer) Close

func (d *DeltaProducer) Close() error

Close the DeltaProducer

func (*DeltaProducer) Commit

func (d *DeltaProducer) Commit() (string, error)

Commit will attempt to produce a delta between the 2 eopkg files This will be performed in temporary storage so must then be copied into the final resting location, and unlinked, before it can be used.

type Dependency

type Dependency struct {
	Name string `xml:",chardata"` // Value of the dependency

	// Release based dependencies
	ReleaseFrom int `xml:"releaseFrom,attr,omitempty"` // >= release
	ReleaseTo   int `xml:"releaseTo,attr,omitempty"`   // <= release
	Release     int `xml:"release,attr,omitempty"`     // == release

	// Version based dependencies
	VersionFrom string `xml:"versionFrom,attr,omitempty"` // >= version
	VersionTo   string `xml:"versionTo,attr,omitempty"`   // <= version
	Version     string `xml:"version,attr,omitempty"`     // == version
}

A Dependency has various attributes which help determine what needs to be installed when updating or installing the package.

type Distribution

type Distribution struct {
	SourceName string // Name of source to match source repos

	// Translated description
	Description []struct {
		Value string `xml:",cdata"`
		Lang  string `xml:"lang,attr,omitempty"`
	}

	Version    string // Published version number for compatibility
	Type       string // Type of repository (should always be main, really. Just descriptive)
	BinaryName string // Name of the binary repository

	Obsoletes []string `xml:"Obsoletes>Package"` // Package names that are no longer supported
	// contains filtered or unexported fields
}

A Distribution as seen through the eyes of XML

func NewDistribution

func NewDistribution(xmlfile string) (*Distribution, error)

NewDistribution will load the Distribution data from the XML file

func (*Distribution) IsObsolete

func (d *Distribution) IsObsolete(id string) bool

IsObsolete will allow quickly determination of whether the package name was marked obsolete and should be hidden from the index

type File

type File struct {
	Path      string
	Type      string
	Size      int64  `xml:"Size,omitempty"`
	UID       int    `xml:"Uid,omitempty"`
	GID       int    `xml:"Gid,omitempty"`
	Mode      string `xml:"Mode,omitempty"`
	Hash      string `xml:"Hash,omitempty"`
	Permanent string `xml:"Permanent,omitempty"`
	// contains filtered or unexported fields
}

File is the idoimatic representation of the XML <File> node

Note that directories are indicated by a missing hash. Unfortunately however eopkg doesn't record the actual _type_ of a file in an intelligent sense, thus we'll have to deal with symlinks separately.

In an ideal world the package archive would be hash indexed with no file names or special permissions inside the archive, and we'd record all relevant metadata. This would allow a single copy, many hardlink approach to blit the files out, as well as allowing us to more accurately represent symbolic links instead of pretending they're real files.

Long story short: Wait for eopkg's successor to worry about this stuff.

func (*File) FileMode

func (f *File) FileMode() os.FileMode

FileMode will return an os.FileMode version of our string encoded "Mode" member

func (*File) IsDir

func (f *File) IsDir() bool

IsDir is a very trivial helper to determine if the file is meant to be a directory.

type Files

type Files struct {
	File []*File
}

Files is the idiomatic representation of the XML <Files> node with one or more <File> children

type Group

type Group struct {
	Name string // ID of this group, i.e. "multimedia"

	// Translated short name
	LocalName []LocalisedField

	Icon string // Display icon for this Group
}

A Group as seen through the eyes of XML

type GroupSort

type GroupSort []Group

GroupSort allows us to quickly sort our groups by name

func (GroupSort) Len

func (g GroupSort) Len() int

func (GroupSort) Less

func (g GroupSort) Less(a, b int) bool

func (GroupSort) Swap

func (g GroupSort) Swap(a, b int)

type Groups

type Groups struct {
	Groups []Group `xml:"Groups>Group"`
}

Groups is a simple helper wrapper for loading from components.xml files

func NewGroups

func NewGroups(xmlfile string) (*Groups, error)

NewGroups will load the Groups data from the XML file

type LocalisedField

type LocalisedField struct {
	Value string `xml:",cdata"`
	Lang  string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"`
}

LocalisedField is used in various parts of the eopkg metadata to provide a field value with an xml:lang attribute describing the language

type MetaPackage

type MetaPackage struct {

	// Main details
	Name string // Name of this binary package

	// Brief description, one line, of the package functionality
	Summary []LocalisedField

	// A full fleshed description of the package
	Description []LocalisedField

	IsA                 string        `xml:"IsA,omitempty"`    // Legacy construct defining type
	PartOf              string        `xml:"PartOf,omitempty"` // Which component the package belongs to
	License             []string      // The package license(s)
	RuntimeDependencies *[]Dependency `xml:"RuntimeDependencies>Dependency,omitempty"` // Packages this package depends on at runtime
	Conflicts           *[]string     `xml:"Conflicts>Package,omitempty"`              // Conflicts with some package
	Replaces            *[]string     `xml:"Replaces>Package,omitempty"`               // Replaces the named package
	Provides            *Provides     `xml:"Provides,omitempty"`
	History             []Update      `xml:"History>Update"` // A series of updates to the package

	// Binary details
	BuildHost           string // Which build server produced the package
	Distribution        string // Identifier for the distribution, i.e. "Solus"
	DistributionRelease string // Name/ID if this distro release, i.e. "1"
	Architecture        string // i.e. x86_64
	InstalledSize       int64  // How much disk space this package takes up
	PackageSize         int64  // Actual size on disk of the .eopkg
	PackageHash         string // Sha1sum for this package
	PackageURI          string // Relative location to the package

	// DeltaPackages are only emitted in the index itself
	DeltaPackages *[]Delta `xml:"DeltaPackages>Delta,omitempty"`

	PackageFormat string // Locked to 1.2 for eopkg

	// Index needs this, so do we for source==release matching
	Source Source // Duplicate source to satisfy indexing
}

A MetaPackage is the Package section of the metadata file. It contains the main details that are important to users.

func (*MetaPackage) GetID

func (m *MetaPackage) GetID() string

GetID will return the package ID for ferryd

func (*MetaPackage) GetPathComponent

func (m *MetaPackage) GetPathComponent() string

GetPathComponent will get the source part of the string which is used in all subdirectories of the repository.

For all packages with a source name of 4 or more characters, the path component will be split on this, i.e.:

libr/libreoffice

For all other packages, the first letter of the source name is used, i.e.:

n/nano

func (*MetaPackage) GetRelease

func (m *MetaPackage) GetRelease() int

GetRelease is a helpful wrapper to return the package's current release

func (*MetaPackage) GetVersion

func (m *MetaPackage) GetVersion() string

GetVersion is a helpful wrapper to return the package's current version

type Metadata

type Metadata struct {
	Source  Source      // Source of this package
	Package MetaPackage `xml:"Package"` // Meta on the package itself
}

Metadata contains all of the information a package can provide to a user prior to installation. This includes the name, version, release, and so forth.

Every Package contains Metadata, and during eopkg indexing, a reduced version of the Metadata is emitted.

type Package

type Package struct {
	Path  string    // Path to this .eopkg file
	ID    string    // Basename of the package, unique.
	Meta  *Metadata // Metadata for this package
	Files *Files    // Files for this package
	// contains filtered or unexported fields
}

A Package is used for accessing a `.eopkg` archive, the current format used within Solus for software packages.

An .eopkg archive is actually a ZIP archive. Internally it has the following structure:

metadata.xml    -> Package information
files.xml       -> Record of the files and hash/uid/gid/etc
comar/          -> Postinstall scripts
install.tar.xz  -> Filesystem contents

Due to this toplevel simplicity, we can use golang's native `archive/zip` library to achieve eopkg access, and parse the contents accordingly. This is much faster than having to call out to the host side tool, which is presently written in Python.

func Open

func Open(path string) (*Package, error)

Open will attempt to open the given .eopkg file. This must be a valid .eopkg file and this stage will assert that it is indeed a real archive.

func (*Package) Close

func (p *Package) Close() error

Close a previously opened .eopkg file

func (*Package) ExtractTarball

func (p *Package) ExtractTarball(directory string) error

ExtractTarball will fully extract install.tar.xz to the destination direction + install.tar suffix

func (*Package) FindFile

func (p *Package) FindFile(path string) *zip.File

FindFile will search for the given name in the .zip's file headers. We do not need to worry about the issue with the Name member being the basename, as the filenames are always unique.

In the event of the file requested not being found, we return nil. The caller should then bail and indicate that the eopkg is corrupted.

func (*Package) ReadAll

func (p *Package) ReadAll() error

ReadAll will read both the metadata + files xml files

func (*Package) ReadFiles

func (p *Package) ReadFiles() error

ReadFiles will read the `files.xml` file within the archive and deserialize it into something accessible within the .eopkg container.

func (*Package) ReadMetadata

func (p *Package) ReadMetadata() error

ReadMetadata will read the `metadata.xml` file within the archive and deserialize it into something accessible within the .eopkg container.

type PackageSet

type PackageSet []*MetaPackage

PackageSet provides sorting capabilities for a slice of packages

func (PackageSet) Len

func (p PackageSet) Len() int

func (PackageSet) Less

func (p PackageSet) Less(a, b int) bool

func (PackageSet) Swap

func (p PackageSet) Swap(a, b int)

type Packager

type Packager struct {
	Name  string // Packager's name
	Email string // Packager's email address
}

A Packager identifies the person responsible for maintaining the source package. In terms of ypkg builds, it will indicate the last person who made a change to the package, allowing a natural "blame" system to work much like git.

type Provides

type Provides struct {
	COMAR       []COMAR  `xml:"COMAR,omitempty"`
	PkgConfig   []string `xml:"PkgConfig,omitempty"`
	PkgConfig32 []string `xml:"PkgConfig32,omitempty"`
}

Provides defines special items that might be exported by a package

type Source

type Source struct {
	Name     string   // Source name
	Homepage string   `xml:"Homepage,omitempty"` // From whence it came
	Packager Packager // Who is responsible for packaging this source.
}

Source provides the information relating to the source package within each binary package. This source identifies one or more packages coming from the same origin, i.e they have the same *source name*.

type Update

type Update struct {
	Release int    `xml:"release,attr"`        // Relno for this update
	Type    string `xml:"type,attr,omitempty"` // i.e. security
	Date    string // When the update was issued
	Version string // Version of the package at the time of this update
	Comment struct {
		Value string `xml:",cdata"` // Comment explaining  the update
	}
	Name struct {
		Value string `xml:",cdata"` // Updater's name
	}
	Email string // Updater's email

	Requires *[]Action `xml:"Requires>Action,omitempty"`
}

An Update forms part of a package's history, describing the version, release, etc, for each release of the package.

Jump to

Keyboard shortcuts

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