func Validate(info *Info) (err error) {
	if info.Name == "" {
		return ErrFieldEmpty{"name"}
	}
	if info.Arch == "" {
		return ErrFieldEmpty{"arch"}
	}
	if info.Version == "" {
		return ErrFieldEmpty{"version"}
	}
	contents, err := files.ExpandContentGlobs(info.Contents, info.DisableGlobbing)
	if err != nil {
		return err
	}
	info.Contents = contents
	return nil
}
Validate the given Info and returns an error if it is invalid.
package nfpm
import (
	"fmt"
	"io"
	"os"
	"sync"
	"github.com/AlekSi/pointer"
	"github.com/Masterminds/semver/v3"
	"github.com/goreleaser/chglog"
	"github.com/goreleaser/nfpm/v2/files"
	"github.com/imdario/mergo"
	"gopkg.in/yaml.v3"
)
var (
	packagers = map[string]Packager{}
	lock      sync.Mutex
)
func RegisterPackager(format string, p Packager) {
	lock.Lock()
	defer lock.Unlock()
	packagers[format] = p
}
func ClearPackagers() {
	lock.Lock()
	defer lock.Unlock()
	packagers = map[string]Packager{}
}
type ErrNoPackager struct {
	format string
}
func (e ErrNoPackager) Error() string {
	return fmt.Sprintf("no packager registered for the format %s", e.format)
}
func Get(format string) (Packager, error) {
	p, ok := packagers[format]
	if !ok {
		return nil, ErrNoPackager{format}
	}
	return p, nil
}
func Parse(in io.Reader) (config Config, err error) {
	return ParseWithEnvMapping(in, os.Getenv)
}
func ParseWithEnvMapping(in io.Reader, mapping func(string) string) (config Config, err error) {
	dec := yaml.NewDecoder(in)
	dec.KnownFields(true)
	if err = dec.Decode(&config); err != nil {
		return
	}
	config.envMappingFunc = mapping
	if config.envMappingFunc == nil {
		config.envMappingFunc = func(s string) string { return s }
	}
	config.expandEnvVars()
	WithDefaults(&config.Info)
	return config, config.Validate()
}
func ParseFile(path string) (config Config, err error) {
	return ParseFileWithEnvMapping(path, os.Getenv)
}
func ParseFileWithEnvMapping(path string, mapping func(string) string) (config Config, err error) {
	var file *os.File
	file, err = os.Open(path)  
	if err != nil {
		return
	}
	defer file.Close()  
	return ParseWithEnvMapping(file, mapping)
}
type Packager interface {
	Package(info *Info, w io.Writer) error
	ConventionalFileName(info *Info) string
}
type Config struct {
	Info           `yaml:",inline"`
	Overrides      map[string]Overridables `yaml:"overrides,omitempty" jsonschema:"title=overrides,description=override some fields when packaging with a specific packager,enum=apk,enum=deb,enum=rpm"`
	envMappingFunc func(string) string
}
func (c *Config) Get(format string) (info *Info, err error) {
	info = &Info{}
	if err = mergo.Merge(info, c.Info); err != nil {
		return nil, fmt.Errorf("failed to merge config into info: %w", err)
	}
	override, ok := c.Overrides[format]
	if !ok {
		return info, nil
	}
	if err = mergo.Merge(&info.Overridables, override, mergo.WithOverride); err != nil {
		return nil, fmt.Errorf("failed to merge overrides into info: %w", err)
	}
	var contents []*files.Content
	for _, f := range info.Contents {
		if f.Packager == format || f.Packager == "" {
			contents = append(contents, f)
		}
	}
	info.Contents = contents
	return info, nil
}
func (c *Config) Validate() error {
	if err := Validate(&c.Info); err != nil {
		return err
	}
	for format := range c.Overrides {
		if _, err := Get(format); err != nil {
			return err
		}
	}
	return nil
}
func (c *Config) expandEnvVars() {
	c.Info.Release = os.Expand(c.Info.Release, c.envMappingFunc)
	c.Info.Version = os.Expand(c.Info.Version, c.envMappingFunc)
	c.Info.Prerelease = os.Expand(c.Info.Prerelease, c.envMappingFunc)
	c.Info.Arch = os.Expand(c.Info.Arch, c.envMappingFunc)
	c.Info.Deb.Signature.KeyFile = os.Expand(c.Deb.Signature.KeyFile, c.envMappingFunc)
	c.Info.RPM.Signature.KeyFile = os.Expand(c.RPM.Signature.KeyFile, c.envMappingFunc)
	c.Info.APK.Signature.KeyFile = os.Expand(c.APK.Signature.KeyFile, c.envMappingFunc)
	c.Info.Deb.Signature.KeyID = pointer.ToString(os.Expand(pointer.GetString(c.Deb.Signature.KeyID), c.envMappingFunc))
	c.Info.RPM.Signature.KeyID = pointer.ToString(os.Expand(pointer.GetString(c.RPM.Signature.KeyID), c.envMappingFunc))
	c.Info.APK.Signature.KeyID = pointer.ToString(os.Expand(pointer.GetString(c.APK.Signature.KeyID), c.envMappingFunc))
	generalPassphrase := os.Expand("$NFPM_PASSPHRASE", c.envMappingFunc)
	c.Info.Deb.Signature.KeyPassphrase = generalPassphrase
	c.Info.RPM.Signature.KeyPassphrase = generalPassphrase
	c.Info.APK.Signature.KeyPassphrase = generalPassphrase
	debPassphrase := os.Expand("$NFPM_DEB_PASSPHRASE", c.envMappingFunc)
	if debPassphrase != "" {
		c.Info.Deb.Signature.KeyPassphrase = debPassphrase
	}
	rpmPassphrase := os.Expand("$NFPM_RPM_PASSPHRASE", c.envMappingFunc)
	if rpmPassphrase != "" {
		c.Info.RPM.Signature.KeyPassphrase = rpmPassphrase
	}
	apkPassphrase := os.Expand("$NFPM_APK_PASSPHRASE", c.envMappingFunc)
	if apkPassphrase != "" {
		c.Info.APK.Signature.KeyPassphrase = apkPassphrase
	}
}
type Info struct {
	Overridables    `yaml:",inline"`
	Name            string `yaml:"name" jsonschema:"title=package name"`
	Arch            string `yaml:"arch" jsonschema:"title=target architecture,example=amd64"`
	Platform        string `yaml:"platform,omitempty" jsonschema:"title=target platform,example=linux,default=linux"`
	Epoch           string `yaml:"epoch,omitempty" jsonschema:"title=version epoch,example=2,default=extracted from version"`
	Version         string `yaml:"version" jsonschema:"title=version,example=v1.0.2,example=2.0.1"`
	VersionSchema   string `yaml:"version_schema,omitempty" jsonschema:"title=version schema,enum=semver,enum=none,default=semver"`
	Release         string `yaml:"release,omitempty" jsonschema:"title=version release,example=1"`
	Prerelease      string `yaml:"prerelease,omitempty" jsonschema:"title=version prerelease,default=extracted from version"`
	VersionMetadata string `yaml:"version_metadata,omitempty" jsonschema:"title=version metadata,example=git"`
	Section         string `yaml:"section,omitempty" jsonschema:"title=package section,example=default"`
	Priority        string `yaml:"priority,omitempty" jsonschema:"title=package priority,example=extra"`
	Maintainer      string `yaml:"maintainer,omitempty" jsonschema:"title=package maintainer,example=me@example.com"`
	Description     string `yaml:"description,omitempty" jsonschema:"title=package description"`
	Vendor          string `yaml:"vendor,omitempty" jsonschema:"title=package vendor,example=MyCorp"`
	Homepage        string `yaml:"homepage,omitempty" jsonschema:"title=package homepage,example=https://example.com"`
	License         string `yaml:"license,omitempty" jsonschema:"title=package license,example=MIT"`
	Changelog       string `yaml:"changelog,omitempty" jsonschema:"title=package changelog,example=changelog.yaml,description=see https://github.com/goreleaser/chglog for more details"`
	DisableGlobbing bool   `yaml:"disable_globbing,omitempty" jsonschema:"title=wether to disable file globbing,default=false"`
	Target          string `yaml:"-"`
}
func (i *Info) Validate() error {
	return Validate(i)
}
func (i *Info) GetChangeLog() (log *chglog.PackageChangeLog, err error) {
	if _, err = os.Stat(i.Changelog); os.IsNotExist(err) {
		return nil, err
	}
	entries, err := chglog.Parse(i.Changelog)
	if err != nil {
		return nil, err
	}
	return &chglog.PackageChangeLog{
		Name:    i.Name,
		Entries: entries,
	}, nil
}
func (i *Info) parseSemver() {
	if v, err := semver.NewVersion(i.Version); err == nil {
		i.Version = fmt.Sprintf("%d.%d.%d", v.Major(), v.Minor(), v.Patch())
		if i.Prerelease == "" {
			i.Prerelease = v.Prerelease()
		}
		if i.VersionMetadata == "" {
			i.VersionMetadata = v.Metadata()
		}
	}
}
type Overridables struct {
	Replaces     []string       `yaml:"replaces,omitempty" jsonschema:"title=replaces directive,example=nfpm"`
	Provides     []string       `yaml:"provides,omitempty" jsonschema:"title=provides directive,example=nfpm"`
	Depends      []string       `yaml:"depends,omitempty" jsonschema:"title=depends directive,example=nfpm"`
	Recommends   []string       `yaml:"recommends,omitempty" jsonschema:"title=recommends directive,example=nfpm"`
	Suggests     []string       `yaml:"suggests,omitempty" jsonschema:"title=suggests directive,example=nfpm"`
	Conflicts    []string       `yaml:"conflicts,omitempty" jsonschema:"title=conflicts directive,example=nfpm"`
	Contents     files.Contents `yaml:"contents,omitempty" jsonschema:"title=files to add to the package"`
	EmptyFolders []string       `yaml:"empty_folders,omitempty" jsonschema:"title=empty folders to be created when installing the package,example=/var/log/nfpm"`
	Scripts      Scripts        `yaml:"scripts,omitempty" jsonschema:"title=scripts to execute"`
	RPM          RPM            `yaml:"rpm,omitempty" jsonschema:"title=rpm-specific settings"`
	Deb          Deb            `yaml:"deb,omitempty" jsonschema:"title=deb-specific settings"`
	APK          APK            `yaml:"apk,omitempty" jsonschema:"title=apk-specific settings"`
}
type RPM struct {
	Scripts     RPMScripts   `yaml:"scripts,omitempty" jsonschema:"title=rpm-specific scripts"`
	Group       string       `yaml:"group,omitempty" jsonschema:"title=package group,example=Unspecified"`
	Summary     string       `yaml:"summary,omitempty" jsonschema:"title=package summary"`
	Compression string       `yaml:"compression,omitempty" jsonschema:"title=compression algorithm to be used,enum=gzip,enum=lzma,enum=xz,default=gzip"`
	Signature   RPMSignature `yaml:"signature,omitempty" jsonschema:"title=rpm signature"`
}
type RPMScripts struct {
	PreTrans  string `yaml:"pretrans,omitempty" jsonschema:"title=pretrans script"`
	PostTrans string `yaml:"posttrans,omitempty" jsonschema:"title=posttrans script"`
}
type PackageSignature struct {
	KeyFile       string  `yaml:"key_file,omitempty" jsonschema:"title=key file,example=key.gpg"`
	KeyID         *string `yaml:"key_id,omitempty" jsonschema:"title=key id,example=bc8acdd415bd80b3"`
	KeyPassphrase string  `yaml:"-"`  
}
type RPMSignature struct {
	PackageSignature `yaml:",inline"`
}
type APK struct {
	Signature APKSignature `yaml:"signature,omitempty" jsonschema:"title=apk signature"`
	Scripts   APKScripts   `yaml:"scripts,omitempty" jsonschema:"title=apk scripts"`
}
type APKSignature struct {
	PackageSignature `yaml:",inline"`
	KeyName string `yaml:"key_name,omitempty" jsonschema:"title=key name,example=origin,default=maintainer_email.rsa.pub"`
}
type APKScripts struct {
	PreUpgrade  string `yaml:"preupgrade,omitempty" jsonschema:"title=pre upgrade script"`
	PostUpgrade string `yaml:"postupgrade,omitempty" jsonschema:"title=post upgrade script"`
}
type Deb struct {
	Scripts     DebScripts   `yaml:"scripts,omitempty" jsonschema:"title=scripts"`
	Triggers    DebTriggers  `yaml:"triggers,omitempty" jsonschema:"title=triggers"`
	Breaks      []string     `yaml:"breaks,omitempty" jsonschema:"title=breaks"`
	Signature   DebSignature `yaml:"signature,omitempty" jsonschema:"title=signature"`
	Compression string       `yaml:"compression,omitempty" jsonschema:"title=compression algorithm to be used,enum=gzip,enum=xz,enum=none,default=gzip"`
}
type DebSignature struct {
	PackageSignature `yaml:",inline"`
	Type string `yaml:"type,omitempty" jsonschema:"title=signer role,enum=origin,enum=maint,enum=archive,default=origin"`
}
type DebTriggers struct {
	Interest        []string `yaml:"interest,omitempty" jsonschema:"title=interest"`
	InterestAwait   []string `yaml:"interest_await,omitempty" jsonschema:"title=interest await"`
	InterestNoAwait []string `yaml:"interest_noawait,omitempty" jsonschema:"title=interest noawait"`
	Activate        []string `yaml:"activate,omitempty" jsonschema:"title=activate"`
	ActivateAwait   []string `yaml:"activate_await,omitempty" jsonschema:"title=activate await"`
	ActivateNoAwait []string `yaml:"activate_noawait,omitempty" jsonschema:"title=activate noawait"`
}
type DebScripts struct {
	Rules     string `yaml:"rules,omitempty" jsonschema:"title=rules"`
	Templates string `yaml:"templates,omitempty" jsonschema:"title=templates"`
	Config    string `yaml:"config,omitempty" jsonschema:"title=config"`
}
type Scripts struct {
	PreInstall  string `yaml:"preinstall,omitempty" jsonschema:"title=pre install"`
	PostInstall string `yaml:"postinstall,omitempty" jsonschema:"title=post install"`
	PreRemove   string `yaml:"preremove,omitempty" jsonschema:"title=pre remove"`
	PostRemove  string `yaml:"postremove,omitempty" jsonschema:"title=post remove"`
}
type ErrFieldEmpty struct {
	field string
}
func (e ErrFieldEmpty) Error() string {
	return fmt.Sprintf("package %s must be provided", e.field)
}