Files
src.dualinventive.com/go/common/vendor/github.com/xor-gate/debpkg/control.go
2024-08-09 12:10:16 +02:00

337 lines
12 KiB
Go

// Copyright 2017 Debpkg authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.
package debpkg
import (
"fmt"
"io/ioutil"
"math"
"strings"
"github.com/xor-gate/debpkg/internal/targzip"
)
type control struct {
tgz *targzip.TarGzip
info controlInfo
conffiles string // List of configuration-files
hasCustomConffiles bool
}
type controlInfoVersion struct {
full string // Full version string. E.g "0.1.2"
major uint // Major version number
minor uint // Minor version number
patch uint // Patch version number
}
type controlInfo struct {
name string
version controlInfoVersion
architecture string
maintainer string
maintainerEmail string
homepage string
depends string
recommends string
suggests string
conflicts string
provides string
replaces string
section string
priority Priority
descrShort string // Short package description
descr string // Long package description
vcsType VcsType // E.g: "Svn", "Git" etcetera
vcsURL string // E.g: git@github.com:xor-gate/debpkg.git
vcsBrowser string // E.g: https://github.com/xor-gate/debpkg
builtUsing string // E.g: gcc-4.6 (= 4.6.0-11)
}
// SetName sets the name of the binary package (mandatory)
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Package
func (deb *DebPkg) SetName(name string) {
deb.control.info.name = name
}
// SetVersion sets the full version string (mandatory), or use SetVersion* functions for "major.minor.patch"
// The upstream_version may contain only alphanumerics ( A-Za-z0-9 ) and the characters . + - : ~
// (full stop, plus, hyphen, colon, tilde) and should start with a digit.
// NOTE: When the full string is set the other SetVersion* function calls are ignored
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
func (deb *DebPkg) SetVersion(version string) {
deb.control.info.version.full = version
}
// SetVersionMajor sets the version major number
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
func (deb *DebPkg) SetVersionMajor(major uint) {
deb.control.info.version.major = major
}
// SetVersionMinor sets the version minor number
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
func (deb *DebPkg) SetVersionMinor(minor uint) {
deb.control.info.version.minor = minor
}
// SetVersionPatch sets the version patch level
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
func (deb *DebPkg) SetVersionPatch(patch uint) {
deb.control.info.version.patch = patch
}
// SetArchitecture sets the architecture of the package where it can be installed.
// E.g "i386, amd64, arm, any, all". See `dpkg-architecture -L` for all supported.
// Architecture: any
// The generated binary package is an architecture dependent one usually in a compiled language.
// Architecture: all
// The generated binary package is an architecture independent one usually consisting of text,
// images, or scripts in an interpreted language.
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Architecture
// And: http://man7.org/linux/man-pages/man1/dpkg-architecture.1.html
func (deb *DebPkg) SetArchitecture(arch string) {
deb.control.info.architecture = arch
}
// SetMaintainer (mandatory), sets the package maintainers name and surname. E.g: "Foo Bar"
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Maintainer
func (deb *DebPkg) SetMaintainer(maintainer string) {
deb.control.info.maintainer = maintainer
}
// SetMaintainerEmail sets the package maintainers email address. E.g: "foo@bar.com"
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Maintainer
func (deb *DebPkg) SetMaintainerEmail(email string) {
deb.control.info.maintainerEmail = email
}
// SetDepends sets the package dependencies. E.g: "lsb-release"
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
func (deb *DebPkg) SetDepends(depends string) {
deb.control.info.depends = depends
}
// SetRecommends sets the package recommendations. E.g: "aptitude"
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
func (deb *DebPkg) SetRecommends(recommends string) {
deb.control.info.recommends = recommends
}
// SetSuggests sets the package suggestions. E.g: "aptitude"
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
func (deb *DebPkg) SetSuggests(suggests string) {
deb.control.info.suggests = suggests
}
// SetConflicts sets one or more conflicting packages. E.g: "nano"
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html#s-conflicts
func (deb *DebPkg) SetConflicts(conflicts string) {
deb.control.info.conflicts = conflicts
}
// SetProvides sets the type which the package provides. E.g: "editor"
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html#s-virtual
func (deb *DebPkg) SetProvides(provides string) {
deb.control.info.provides = provides
}
// SetReplaces sets the names of packages which will be replaced. E.g: "pico"
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html
func (deb *DebPkg) SetReplaces(replaces string) {
deb.control.info.replaces = replaces
}
// SetPriority (recommended). Default set to debpkg.PriorityUnset
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Priority
// And: https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities
func (deb *DebPkg) SetPriority(priority Priority) {
deb.control.info.priority = priority
}
// SetSection (recommended). E.g: editors
// See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Section
// And: https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
func (deb *DebPkg) SetSection(section string) {
deb.control.info.section = section
}
// SetHomepage sets the homepage URL of the package. E.g: "https://github.com/foo/bar"
func (deb *DebPkg) SetHomepage(url string) {
deb.control.info.homepage = url
}
// SetShortDescription sets the single line synopsis. E.g: "My awesome foo bar baz tool"
func (deb *DebPkg) SetShortDescription(descr string) {
deb.control.info.descrShort = descr
}
// SetDescription sets the extended description over several lines. E.g:
// "This tool will calculation the most efficient way to world domination"
// NOTE: The debian control file has a special formatting of the long description
// this function replaces newlines with a newline and a space.
func (deb *DebPkg) SetDescription(descr string) {
deb.control.info.descr = " " + strings.Replace(descr, "\n", "\n ", -1)
}
// SetVcsType sets the version control system (Vcs) type for the source package.
// See: https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#s6.2.5.2
func (deb *DebPkg) SetVcsType(vcs VcsType) {
deb.control.info.vcsType = vcs
}
// SetVcsURL sets the version control system (Vcs) URL for the source package.
// See: https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#s6.2.5.2
func (deb *DebPkg) SetVcsURL(url string) {
deb.control.info.vcsURL = url
}
// SetVcsBrowser sets the version control system (Vcs) browsable source-tree URL for the source package.
// See: https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#s6.2.5.2
func (deb *DebPkg) SetVcsBrowser(url string) {
deb.control.info.vcsBrowser = url
}
// SetBuiltUsing incorporate parts of other packages when built but do not have to depend on those packages.
// A package using the source code from the gcc-4.6-source binary package built from the gcc-4.6 source package
// would have this field in its control file:
// Built-Using: gcc-4.6 (= 4.6.0-11)
// A package including binaries from grub2 and loadlin would have this field in its control file:
// Built-Using: grub2 (= 1.99-9), loadlin (= 1.6e-1)
// See: https://www.debian.org/doc/debian-policy/ch-relationships.html#s-built-using
func (deb *DebPkg) SetBuiltUsing(info string) {
deb.control.info.builtUsing = info
}
// AddControlExtraString is the same as AddControlExtra except it uses a string input.
// the files have possible DOS line-endings replaced by UNIX line-endings
func (deb *DebPkg) AddControlExtraString(name, s string) error {
if name == "conffiles" {
deb.control.hasCustomConffiles = true
}
s = strings.Replace(s, "\r\n", "\n", -1)
return deb.control.tgz.AddFileFromBuffer(name, []byte(s))
}
// AddControlExtra allows the advanced user to add custom script to the control.tar.gz Typical usage is
// for preinst, postinst, postrm, prerm: https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
// And: https://www.debian.org/doc/manuals/maint-guide/dother.en.html#maintscripts
// the files have possible DOS line-endings replaced by UNIX line-endings
func (deb *DebPkg) AddControlExtra(name, filename string) error {
b, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
return deb.AddControlExtraString(name, string(b))
}
// verify the control file for validity
func (c *control) verify() error {
if c.info.name == "" {
return fmt.Errorf("empty package name")
}
if c.info.architecture == "" {
return fmt.Errorf("empty architecture")
}
return nil
}
func (c *control) markConfigFile(dest string) error {
if dest == "" {
return fmt.Errorf("config file cannot be empty")
}
c.conffiles += dest + "\n"
return nil
}
// finalizeControlFile creates the actual control-file, adds MD5-sums and stores
// config-files
func (c *control) finalizeControlFile(d *data) error {
if !c.hasCustomConffiles {
if err := c.tgz.AddFileFromBuffer("conffiles", []byte(c.conffiles)); err != nil {
return err
}
}
controlFile := []byte(c.String(d.tgz.Written()))
if err := c.tgz.AddFileFromBuffer("control", controlFile); err != nil {
return err
}
if err := c.tgz.AddFileFromBuffer("md5sums", []byte(d.md5sums)); err != nil {
return err
}
return nil
}
// Generate version string (e.g "1.2.3") from major,minor patch or from full version
func (c *control) version() string {
if c.info.version.full != "" {
return c.info.version.full
}
return fmt.Sprintf("%d.%d.%d",
c.info.version.major,
c.info.version.minor,
c.info.version.patch)
}
func (c *control) size() int64 {
return c.tgz.Size()
}
// Create control file for control.tar.gz
func (c *control) String(installedSize uint64) string {
var o string
o += fmt.Sprintf("Package: %s\n", c.info.name)
o += fmt.Sprintf("Version: %s\n", c.version())
o += fmt.Sprintf("Architecture: %s\n", c.info.architecture)
o += fmt.Sprintf("Maintainer: %s <%s>\n",
c.info.maintainer,
c.info.maintainerEmail)
o += fmt.Sprintf("Installed-Size: %d\n", uint64(math.Ceil(float64(installedSize)/1024)))
if c.info.section != "" {
o += fmt.Sprintf("Section: %s\n", c.info.section)
}
if c.info.priority != PriorityUnset {
o += fmt.Sprintf("Priority: %s\n", c.info.priority)
}
if c.info.homepage != "" {
o += fmt.Sprintf("Homepage: %s\n", c.info.homepage)
}
if c.info.vcsType != VcsTypeUnset && c.info.vcsURL != "" {
o += fmt.Sprintf("Vcs-%s: %s\n", c.info.vcsType, c.info.vcsURL)
}
if c.info.vcsBrowser != "" {
o += fmt.Sprintf("Vcs-Browser: %s\n", c.info.vcsBrowser)
}
if c.info.builtUsing != "" {
o += fmt.Sprintf("Built-Using: %s\n", c.info.builtUsing)
}
if c.info.depends != "" {
o += fmt.Sprintf("Depends: %s\n", c.info.depends)
}
if c.info.recommends != "" {
o += fmt.Sprintf("Recommends: %s\n", c.info.recommends)
}
if c.info.suggests != "" {
o += fmt.Sprintf("Suggests: %s\n", c.info.suggests)
}
if c.info.conflicts != "" {
o += fmt.Sprintf("Conflicts: %s\n", c.info.conflicts)
}
if c.info.provides != "" {
o += fmt.Sprintf("Provides: %s\n", c.info.provides)
}
if c.info.replaces != "" {
o += fmt.Sprintf("Replaces: %s\n", c.info.replaces)
}
o += fmt.Sprintf("Description: %s\n", c.info.descrShort)
o += fmt.Sprintf("%s", c.info.descr)
return o
}