pkglint

package module
v21.1.2+incompatible Latest Latest
Warning

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

Go to latest
Published: May 25, 2021 License: BSD-2-Clause Imports: 34 Imported by: 0

README

Build Status codecov

pkglint checks whether a pkgsrc package conforms to the various conventions established over the years. It produces warnings, errors and notes and, upon request, explains them.

Before importing a new package or making changes to an existing package, pkglint should be run in the package's directory to check for common errors.

See https://www.pkgsrc.org/.


For an introduction to programming and extending pkglint, see The pkglint tour.

Documentation

Index

Constants

View Source
const (
	// List is a compound type, consisting of several space-separated elements.
	// Elements can have embedded spaces by enclosing them in double or single
	// quotes, like in the shell.
	//
	// These lists are used in the :M, :S modifiers, in .for loops,
	// and as lists of arbitrary things.
	List vartypeOptions = 1 << iota

	// The variable is not defined by the pkgsrc infrastructure.
	// It follows the common naming convention, therefore its type can be guessed.
	// Sometimes, with files and paths, this leads to wrong decisions.
	Guessed

	// The variable can, or in some cases must, be defined by the package.
	// For several of these variables, the pkgsrc infrastructure provides
	// a reasonable default value, either in bsd.prefs.mk or in bsd.pkg.mk.
	PackageSettable

	// The variable can be defined by the pkgsrc user in mk.conf.
	// Its value is available at load time after bsd.prefs.mk has been included.
	UserSettable

	// This variable is provided by either the pkgsrc infrastructure in
	// mk/*, or by <sys.mk>, which is included at the very beginning.
	//
	// TODO: Clearly distinguish between:
	//  * sys.mk
	//  * bsd.prefs.mk
	//  * bsd.pkg.mk
	//  * other parts of the pkgsrc infrastructure
	//  * environment variables
	//  Having all these possibilities as boolean flags is probably not
	//  expressive enough. This is related to the scope and lifetime of
	//  variables and should be modelled separately.
	//
	// See DefinedInSysMk.
	SystemProvided

	// This variable may be provided in the command line by the pkgsrc
	// user when building a package.
	//
	// Since the values of these variables are not written down in any
	// file, they must not influence the generated binary packages.
	//
	// See UserSettable.
	CommandLineProvided

	// NeedsRationale marks variables that should always contain a comment
	// describing why they are set. Typical examples are NOT_FOR_* variables.
	NeedsRationale

	// When something is appended to this variable, each additional
	// value should be on a line of its own.
	OnePerLine

	// AlwaysInScope is true when the variable is always available.
	//
	// One possibility is that the variable is defined in <sys.mk>,
	// which means that its value is loaded even before the package
	// Makefile is parsed.
	//
	// Another possibility is that the variable is local to a target,
	// such as .TARGET or .IMPSRC.
	//
	// These variables may be used at load time in .if and .for
	// directives even before bsd.prefs.mk is included.
	//
	// XXX: This option is related to the lifetime of the variable.
	//  Other aspects of the lifetime are handled by ACLPermissions,
	//  see aclpUseLoadtime.
	AlwaysInScope

	// DefinedIfInScope is true if the variable is guaranteed to be
	// defined, provided that it is in scope.
	//
	// This means the variable can be used in expressions like ${VAR}
	// without having to add the :U modifier like in ${VAR:U}.
	//
	// This option is independent of the lifetime of the variable,
	// it merely expresses "if the variable is in scope, it is defined".
	// As of December 2019, the lifetime of variables is managed by
	// the ACLPermissions, but is incomplete.
	//
	// TODO: Model the lifetime and scope separately, see SystemProvided.
	//
	// Examples:
	//  MACHINE_PLATFORM (from sys.mk)
	//  PKGPATH (from bsd.prefs.mk)
	//  PREFIX (from bsd.pkg.mk)
	DefinedIfInScope

	// NonemptyIfDefined is true if the variable is guaranteed to be
	// nonempty, provided that the variable is in scope and defined.
	//
	// This is typical for system-provided variables like PKGPATH or
	// MACHINE_PLATFORM, as well as package-settable variables like
	// PKGNAME.
	//
	// This option is independent of the lifetime of the variable,
	// it merely expresses "if the variable is in scope, it is defined".
	// As of December 2019, the lifetime of variables is managed by
	// the ACLPermissions, but is incomplete.
	//
	// TODO: Model the lifetime and scope separately, see SystemProvided.
	//
	// Examples:
	//  MACHINE_PLATFORM (from sys.mk)
	//  PKGPATH (from bsd.prefs.mk)
	//  PREFIX (from bsd.pkg.mk)
	//  PKGNAME (package-settable)
	//  X11_TYPE (user-settable)
	NonemptyIfDefined

	// Unique is true if it doesn't make sense to append the same
	// value more than once to the variable.
	//
	// A typical example is CATEGORIES.
	Unique

	NoVartypeOptions = 0
)
View Source
const SilentAutofixFormat = "SilentAutofixFormat"

SilentAutofixFormat is used in exceptional situations when an autofix action is not directly related to a diagnostic.

To prevent confusion, the code using this magic value must ensure to log a diagnostic by other means.

Variables

View Source
var (
	Error           = &LogLevel{"ERROR", "error"}
	Warn            = &LogLevel{"WARN", "warning"}
	Note            = &LogLevel{"NOTE", "note"}
	AutofixLogLevel = &LogLevel{"AUTOFIX", "autofix"}
)
View Source
var (
	LowerDash = textproc.NewByteSet("a-z---")
	AlnumDot  = textproc.NewByteSet("A-Za-z0-9_.")
)
View Source
var (
	VarbaseBytes  = textproc.NewByteSet("A-Za-z_0-9+---")
	VarparamBytes = textproc.NewByteSet("A-Za-z_0-9#*+---./[")
)

VarbaseBytes contains characters that may be used in the main part of variable names. VarparamBytes contains characters that may be used in the parameter part of variable names.

For example, TOOLS_PATH.[ is a valid variable name but [ alone isn't since the opening bracket is only allowed in the parameter part of variable names.

This approach differs from the one in devel/bmake/files/parse.c:/^Parse_IsVar, but in practice it works equally well. Luckily there aren't many situations where a complicated variable name contains unbalanced parentheses or braces, which would confuse the devel/bmake parser.

TODO: The allowed characters differ between the basename and the parameter

of the variable. The square bracket is only allowed in the parameter part.
View Source
var (
	BtAwkCommand             = &BasicType{"AwkCommand", (*VartypeCheck).AwkCommand}
	BtBasicRegularExpression = &BasicType{"BasicRegularExpression", (*VartypeCheck).BasicRegularExpression}
	BtBuildlinkDepmethod     = &BasicType{"BuildlinkDepmethod", (*VartypeCheck).BuildlinkDepmethod}
	BtCategory               = &BasicType{"Category", (*VartypeCheck).Category}
	BtCFlag                  = &BasicType{"CFlag", (*VartypeCheck).CFlag}
	BtComment                = &BasicType{"Comment", (*VartypeCheck).Comment}
	BtConfFiles              = &BasicType{"ConfFiles", (*VartypeCheck).ConfFiles}
	BtDependencyPattern      = &BasicType{"DependencyPattern", (*VartypeCheck).DependencyPattern}
	BtDependencyWithPath     = &BasicType{"DependencyWithPath", (*VartypeCheck).DependencyWithPath}
	BtDistSuffix             = &BasicType{"DistSuffix", (*VartypeCheck).DistSuffix}
	BtEmulPlatform           = &BasicType{"EmulPlatform", (*VartypeCheck).EmulPlatform}
	BtFetchURL               = &BasicType{"FetchURL", (*VartypeCheck).FetchURL}
	BtFilename               = &BasicType{"Filename", (*VartypeCheck).Filename}
	BtFilePattern            = &BasicType{"FilePattern", (*VartypeCheck).FilePattern}
	BtFileMode               = &BasicType{"FileMode", (*VartypeCheck).FileMode}
	BtGccReqd                = &BasicType{"GccReqd", (*VartypeCheck).GccReqd}
	BtHomepage               = &BasicType{"Homepage", (*VartypeCheck).Homepage}
	BtIdentifierDirect       = &BasicType{"Identifier", (*VartypeCheck).IdentifierDirect}
	BtIdentifierIndirect     = &BasicType{"Identifier", (*VartypeCheck).IdentifierIndirect}
	BtInteger                = &BasicType{"Integer", (*VartypeCheck).Integer}
	BtLdFlag                 = &BasicType{"LdFlag", (*VartypeCheck).LdFlag}
	BtLicense                = &BasicType{"License", (*VartypeCheck).License}
	BtMachineGnuPlatform     = &BasicType{"MachineGnuPlatform", (*VartypeCheck).MachineGnuPlatform}
	BtMachinePlatform        = &BasicType{"MachinePlatform", (*VartypeCheck).MachinePlatform}
	BtMachinePlatformPattern = &BasicType{"MachinePlatformPattern", (*VartypeCheck).MachinePlatformPattern}
	BtMailAddress            = &BasicType{"MailAddress", (*VartypeCheck).MailAddress}
	BtMessage                = &BasicType{"Message", (*VartypeCheck).Message}
	BtOption                 = &BasicType{"Option", (*VartypeCheck).Option}
	BtPathlist               = &BasicType{"Pathlist", (*VartypeCheck).Pathlist}
	BtPathPattern            = &BasicType{"PathPattern", (*VartypeCheck).PathPattern}
	BtPathname               = &BasicType{"Pathname", (*VartypeCheck).Pathname}
	BtPathnameSpace          = &BasicType{"PathnameSpace", (*VartypeCheck).PathnameSpace}
	BtPerl5Packlist          = &BasicType{"Perl5Packlist", (*VartypeCheck).Perl5Packlist}
	BtPerms                  = &BasicType{"Perms", (*VartypeCheck).Perms}
	BtPkgname                = &BasicType{"Pkgname", (*VartypeCheck).Pkgname}
	BtPkgpath                = &BasicType{"Pkgpath", (*VartypeCheck).Pkgpath}
	BtPkgOptionsVar          = &BasicType{"PkgOptionsVar", (*VartypeCheck).PkgOptionsVar}
	BtPkgrevision            = &BasicType{"Pkgrevision", (*VartypeCheck).Pkgrevision}
	BtPlistIdentifier        = &BasicType{"PlistIdentifier", (*VartypeCheck).PlistIdentifier}
	BtPrefixPathname         = &BasicType{"PrefixPathname", (*VartypeCheck).PrefixPathname}
	BtPythonDependency       = &BasicType{"PythonDependency", (*VartypeCheck).PythonDependency}
	BtRPkgName               = &BasicType{"RPkgName", (*VartypeCheck).RPkgName}
	BtRPkgVer                = &BasicType{"RPkgVer", (*VartypeCheck).RPkgVer}
	BtRelativePkgDir         = &BasicType{"RelativePkgDir", (*VartypeCheck).RelativePkgDir}
	BtRelativePkgPath        = &BasicType{"RelativePkgPath", (*VartypeCheck).RelativePkgPath}
	BtRestricted             = &BasicType{"Restricted", (*VartypeCheck).Restricted}
	BtSedCommands            = &BasicType{"SedCommands", (*VartypeCheck).SedCommands}
	BtShellCommand           = &BasicType{"ShellCommand", nil}  // see func init below
	BtShellCommands          = &BasicType{"ShellCommands", nil} // see func init below
	BtShellWord              = &BasicType{"ShellWord", nil}     // see func init below
	BtStage                  = &BasicType{"Stage", (*VartypeCheck).Stage}
	BtToolDependency         = &BasicType{"ToolDependency", (*VartypeCheck).ToolDependency}
	BtToolName               = &BasicType{"ToolName", (*VartypeCheck).ToolName}
	BtUnknown                = &BasicType{"Unknown", (*VartypeCheck).Unknown}
	BtURL                    = &BasicType{"URL", (*VartypeCheck).URL}
	BtUserGroupName          = &BasicType{"UserGroupName", (*VartypeCheck).UserGroupName}
	BtVariableName           = &BasicType{"VariableName", (*VartypeCheck).VariableName}
	BtVariableNamePattern    = &BasicType{"VariableNamePattern", (*VartypeCheck).VariableNamePattern}
	BtVersion                = &BasicType{"Version", (*VartypeCheck).Version}
	BtWrapperReorder         = &BasicType{"WrapperReorder", (*VartypeCheck).WrapperReorder}
	BtWrapperTransform       = &BasicType{"WrapperTransform", (*VartypeCheck).WrapperTransform}
	BtWrkdirSubdirectory     = &BasicType{"WrkdirSubdirectory", (*VartypeCheck).WrkdirSubdirectory}
	BtWrksrcPathPattern      = &BasicType{"WrksrcPathPattern", (*VartypeCheck).WrksrcPathPattern}
	BtWrksrcSubdirectory     = &BasicType{"WrksrcSubdirectory", (*VartypeCheck).WrksrcSubdirectory}
	BtYes                    = &BasicType{"Yes", (*VartypeCheck).Yes}
	BtYesNo                  = &BasicType{"YesNo", (*VartypeCheck).YesNo}
	BtYesNoIndirectly        = &BasicType{"YesNoIndirectly", (*VartypeCheck).YesNoIndirectly}

	BtMachineArch             = enumFromValues(machineArchValues)
	BtMachineGnuArch          = enumFromValues(machineGnuArchValues)
	BtEmulOpsys               = enumFromValues(emulOpsysValues)
	BtEmulArch                = enumFromValues(machineArchValues) // Just a wild guess.
	BtMachineGnuPlatformOpsys = BtEmulOpsys
)

G is the abbreviation for "global state"; this and the tracer are the only global variables in this Go package.

Functions

func CheckFileAlternatives

func CheckFileAlternatives(filename CurrPath, pkg *Package)

func CheckFileMk

func CheckFileMk(filename CurrPath, pkg *Package)

func CheckFileOther

func CheckFileOther(filename CurrPath)

func CheckLinesBuildlink3Mk

func CheckLinesBuildlink3Mk(mklines *MkLines)

func CheckLinesDescr

func CheckLinesDescr(lines *Lines)

func CheckLinesDistinfo

func CheckLinesDistinfo(pkg *Package, lines *Lines)

func CheckLinesMessage

func CheckLinesMessage(lines *Lines, pkg *Package)

func CheckLinesOptionsMk

func CheckLinesOptionsMk(mklines *MkLines, buildlinkID string)

func CheckLinesPatch

func CheckLinesPatch(lines *Lines, pkg *Package)

func CheckLinesPlist

func CheckLinesPlist(pkg *Package, lines *Lines)

func CheckLinesTrailingEmptyLines

func CheckLinesTrailingEmptyLines(lines *Lines)

func CheckdirCategory

func CheckdirCategory(dir CurrPath)

func CheckdirToplevel

func CheckdirToplevel(dir CurrPath)

func IsPrefs

func IsPrefs(filename RelPath) bool

func LoadsPrefs

func LoadsPrefs(filename RelPath) bool

LoadsPrefs returns whether the given file, when included, loads the user preferences.

func NewPlistLineSorter

func NewPlistLineSorter(plines []*PlistLine) *plistLineSorter

func SaveAutofixChanges

func SaveAutofixChanges(lines *Lines) (autofixed bool)

SaveAutofixChanges writes the given lines back into their files, applying the autofix changes. The lines may come from different files. Only files that actually have changed lines are saved.

This only happens in --autofix mode.

Types

type ACLEntry

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

func NewACLEntry

func NewACLEntry(glob string, permissions ACLPermissions) ACLEntry

type ACLPermissions

type ACLPermissions uint8

func (ACLPermissions) Contains

func (perms ACLPermissions) Contains(subset ACLPermissions) bool

Contains returns whether each permission of the given subset is contained in this permission set.

func (ACLPermissions) HumanString

func (perms ACLPermissions) HumanString() string

func (ACLPermissions) String

func (perms ACLPermissions) String() string

type AlternativesChecker

type AlternativesChecker struct{}

func (*AlternativesChecker) Check

func (ck *AlternativesChecker) Check(lines *Lines, pkg *Package)

type Autofix

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

Autofix handles all modifications to a single line, possibly spanning multiple physical lines in case of Makefile lines, describes them in a human-readable form and formats the output. The modifications are kept in memory only, until they are written to disk by SaveAutofixChanges.

func NewAutofix

func NewAutofix(line *Line) *Autofix

func (*Autofix) Apply

func (fix *Autofix) Apply()

Apply does the actual work that has been prepared by previous calls to Errorf, Warnf, Notef, Describef, Replace, Delete and so on.

In default mode, the diagnostic is logged even when nothing has actually been fixed. This frees the calling code from distinguishing the cases where a fix can or cannot be applied automatically.

In --show-autofix mode, only those diagnostics are logged that actually fix something. This is done to hide possibly distracting, unrelated diagnostics.

In --autofix mode, only the actual changes are logged, but not the corresponding diagnostics. To get both, specify --show-autofix as well.

Apply does the modifications only in memory. To actually save them to disk, SaveAutofixChanges needs to be called. For example, this is done by MkLines.Check.

func (*Autofix) Custom

func (fix *Autofix) Custom(fixer func(showAutofix, autofix bool))

Custom runs a custom fix action, unless the fix is skipped anyway because of the --only option.

The fixer function must check whether it can actually fix something, and if so, call Describef to describe the actual fix.

If autofix is false, the fix should be applied, as far as only in-memory data structures are affected, and these are not written back to disk. No externally observable modification must be done. For example, changing the text of Line.raw is appropriate, but changing files in the file system is not.

Only if autofix is true, fixes other than modifying the current Line should be done persistently, such as changes to the file system.

If pkglint is run in --autofix mode, all changes to the lines of a file will be collected in memory and are written back to disk by SaveAutofixChanges, once at the end.

func (*Autofix) Delete

func (fix *Autofix) Delete()

Delete removes the current line completely. It can be combined with InsertBelow or InsertAbove to replace the complete line with some different text.

func (*Autofix) Describef

func (fix *Autofix) Describef(rawIndex int, format string, args ...interface{})

Describef can be called from within an Autofix.Custom call to remember a description of the actual fix for logging it later when Apply is called. Describef may be called multiple times before calling Apply.

func (*Autofix) Errorf

func (fix *Autofix) Errorf(format string, args ...interface{})

Errorf remembers the error for logging it later when Apply is called.

func (*Autofix) Explain

func (fix *Autofix) Explain(explanation ...string)

Explain remembers the explanation for logging it later when Apply is called.

func (*Autofix) InsertAbove

func (fix *Autofix) InsertAbove(text string)

InsertAbove prepends a line above the current line. The newline is added internally.

func (*Autofix) InsertBelow

func (fix *Autofix) InsertBelow(text string)

InsertBelow appends a line below the current line. The newline is added internally.

func (*Autofix) Notef

func (fix *Autofix) Notef(format string, args ...interface{})

Notef remembers the note for logging it later when Apply is called.

func (*Autofix) Replace

func (fix *Autofix) Replace(from string, to string)

Replace replaces "from" with "to", a single time. If the text is not found exactly once, nothing is replaced at all. The diagnostic is given nevertheless, to allow humans to fix it.

func (*Autofix) ReplaceAfter

func (fix *Autofix) ReplaceAfter(prefix, from string, to string)

ReplaceAfter replaces the text "prefix+from" with "prefix+to", a single time. In the diagnostic, only the replacement of "from" with "to" is mentioned. If the text is not found exactly once, nothing is replaced at all.

func (*Autofix) ReplaceAt

func (fix *Autofix) ReplaceAt(rawIndex int, textIndex int, from string, to string)

ReplaceAt replaces the text "from" with "to", a single time. If the text at the given position does not match, ReplaceAt panics.

func (*Autofix) Warnf

func (fix *Autofix) Warnf(format string, args ...interface{})

Warnf remembers the warning for logging it later when Apply is called.

type Autofixer

type Autofixer interface {
	Diagnoser
	Autofix() *Autofix
}

type BasicType

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

func (*BasicType) AllowedEnums

func (bt *BasicType) AllowedEnums() string

func (*BasicType) HasEnum

func (bt *BasicType) HasEnum(value string) bool

func (*BasicType) IsEnum

func (bt *BasicType) IsEnum() bool

func (*BasicType) NeedsQ

func (bt *BasicType) NeedsQ() bool

NeedsQ returns whether variables of this type need the :Q modifier to be safely embedded in other variables or shell programs.

Variables that can consist only of characters like A-Za-z0-9-._ don't need the :Q modifier. All others do, for safety reasons.

type Buildlink3Checker

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

func (*Buildlink3Checker) Check

func (ck *Buildlink3Checker) Check()

type Buildlink3Data

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

func LoadBuildlink3Data

func LoadBuildlink3Data(mklines *MkLines) *Buildlink3Data

type Buildlink3ID

type Buildlink3ID string

Buildlink3ID is the identifier that is used in the BUILDLINK_TREE for referring to a dependent package.

It almost uniquely identifies a package. Packages that are alternatives to each other may use the same identifier.

type Change

type Change struct {
	Location Location
	Action   ChangeAction // Added, Updated, Downgraded, Renamed, Moved, Removed
	Pkgpath  PkgsrcPath   // For renamed or moved packages, the previous PKGPATH

	Author string
	Date   string
	// contains filtered or unexported fields
}

Change describes a modification to a single package, from the doc/CHANGES-* files.

func (*Change) IsAbove

func (ch *Change) IsAbove(other *Change) bool

func (*Change) SuccessorOrVersion

func (ch *Change) SuccessorOrVersion() string

SuccessorOrVersion returns the successor for a Removed package, or the version number of its last appearance. As of 2020-10-06, no cross-validation is done on this field though.

func (*Change) Target

func (ch *Change) Target() PkgsrcPath

Target returns the target PKGPATH for a Renamed or Moved package.

func (*Change) Version

func (ch *Change) Version() string

Version returns the version number for an Added, Updated or Downgraded package.

type ChangeAction

type ChangeAction uint8
const (
	Added ChangeAction = 1 + iota
	Updated
	Downgraded
	Renamed
	Moved
	Removed
)

func ParseChangeAction

func ParseChangeAction(s string) ChangeAction

func (ChangeAction) String

func (ca ChangeAction) String() string

type CurrPath

type CurrPath string

CurrPath is a path that is either absolute or relative to the current working directory. It is used in command line arguments and for loading files from the file system, and later in the diagnostics.

func NewCurrPath

func NewCurrPath(p Path) CurrPath

func NewCurrPathSlash

func NewCurrPathSlash(p string) CurrPath

func NewCurrPathString

func NewCurrPathString(p string) CurrPath

func (CurrPath) AsPath

func (p CurrPath) AsPath() Path

func (CurrPath) Base

func (p CurrPath) Base() RelPath

func (CurrPath) Chmod

func (p CurrPath) Chmod(mode os.FileMode) error

func (CurrPath) Clean

func (p CurrPath) Clean() CurrPath

func (CurrPath) CleanDot

func (p CurrPath) CleanDot() CurrPath

func (CurrPath) CleanPath

func (p CurrPath) CleanPath() CurrPath

func (CurrPath) ContainsPath

func (p CurrPath) ContainsPath(sub Path) bool

func (CurrPath) ContainsText

func (p CurrPath) ContainsText(text string) bool

func (CurrPath) Dir

func (p CurrPath) Dir() CurrPath

func (CurrPath) Exists

func (p CurrPath) Exists() bool

func (CurrPath) GoString

func (p CurrPath) GoString() string

func (CurrPath) HasBase

func (p CurrPath) HasBase(base string) bool

func (CurrPath) HasPrefixPath

func (p CurrPath) HasPrefixPath(prefix CurrPath) bool

func (CurrPath) HasSuffixPath

func (p CurrPath) HasSuffixPath(suffix Path) bool

func (CurrPath) HasSuffixText

func (p CurrPath) HasSuffixText(suffix string) bool

func (CurrPath) IsAbs

func (p CurrPath) IsAbs() bool

func (CurrPath) IsDir

func (p CurrPath) IsDir() bool

func (CurrPath) IsEmpty

func (p CurrPath) IsEmpty() bool

func (CurrPath) IsFile

func (p CurrPath) IsFile() bool

func (CurrPath) JoinClean

func (p CurrPath) JoinClean(other RelPath) CurrPath

func (CurrPath) JoinNoClean

func (p CurrPath) JoinNoClean(other RelPath) CurrPath

func (CurrPath) Lstat

func (p CurrPath) Lstat() (os.FileInfo, error)

func (CurrPath) Open

func (p CurrPath) Open() (*os.File, error)

func (CurrPath) Parts

func (p CurrPath) Parts() []string

func (CurrPath) ReadDir

func (p CurrPath) ReadDir() ([]os.FileInfo, error)

func (CurrPath) ReadPaths

func (p CurrPath) ReadPaths() []CurrPath

func (CurrPath) ReadString

func (p CurrPath) ReadString() (string, error)

func (CurrPath) Rel

func (p CurrPath) Rel(rel CurrPath) RelPath

func (CurrPath) Rename

func (p CurrPath) Rename(newName CurrPath) error

func (CurrPath) ReplaceSuffix

func (p CurrPath) ReplaceSuffix(from string, to string) CurrPath

func (CurrPath) Split

func (p CurrPath) Split() (dir CurrPath, base string)

func (CurrPath) Stat

func (p CurrPath) Stat() (os.FileInfo, error)

func (CurrPath) String

func (p CurrPath) String() string

func (CurrPath) TrimSuffix

func (p CurrPath) TrimSuffix(suffix string) CurrPath

func (CurrPath) WriteString

func (p CurrPath) WriteString(s string) error

type CurrPathQueue

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

func (*CurrPathQueue) Front

func (q *CurrPathQueue) Front() CurrPath

func (*CurrPathQueue) IsEmpty

func (q *CurrPathQueue) IsEmpty() bool

func (*CurrPathQueue) Pop

func (q *CurrPathQueue) Pop() CurrPath

func (*CurrPathQueue) Push

func (q *CurrPathQueue) Push(entries ...CurrPath)

func (*CurrPathQueue) PushFront

func (q *CurrPathQueue) PushFront(entries ...CurrPath)

type CvsEntry

type CvsEntry struct {
	Name      RelPath
	Revision  string
	Timestamp string
	Options   string
	TagDate   string
}

CvsEntry is one of the entries in a CVS/Entries file.

See http://cvsman.com/cvs-1.12.12/cvs_19.php.

type DependencyPattern

type DependencyPattern struct {
	Pkgbase  string // "freeciv-client", "{gcc48,gcc48-libs}", "${EMACS_REQD}"
	LowerOp  string // ">=", ">"
	Lower    string // "2.5.0", "${PYVER}"
	UpperOp  string // "<", "<="
	Upper    string // "3.0", "${PYVER}"
	Wildcard string // "[0-9]*", "1.5.*", "${PYVER}"
}

type Diagnoser

type Diagnoser interface {
	Errorf(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Notef(format string, args ...interface{})
	Explain(explanation ...string)
}

Diagnoser provides the standard way of producing errors, warnings and notes, and explanations for them.

For convenience, it is implemented by several types in pkglint.

type FileCache

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

FileCache reduces the IO load for commonly loaded files by about 50%, especially for buildlink3.mk and *.buildlink3.mk files.

func NewFileCache

func NewFileCache(size int) *FileCache

func (*FileCache) Evict

func (c *FileCache) Evict(filename CurrPath)

func (*FileCache) Get

func (c *FileCache) Get(filename CurrPath, options LoadOptions) *Lines

func (*FileCache) Put

func (c *FileCache) Put(filename CurrPath, options LoadOptions, lines *Lines)

type Hash

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

type HomepageChecker

type HomepageChecker struct {
	Value      string
	ValueNoVar string
	MkLine     *MkLine
	MkLines    *MkLines

	Timeout time.Duration
	// contains filtered or unexported fields
}

HomepageChecker runs the checks for a HOMEPAGE definition.

When pkglint is in network mode (which has to be enabled explicitly using --network), it checks whether the homepage is actually reachable.

The homepage URLs should use https as far as possible. To achieve this goal, the HomepageChecker can migrate homepages from less preferred URLs to preferred URLs.

For most sites, the list of possible URLs is:

  • https://$rest (preferred)
  • http://$rest (less preferred)

For SourceForge, it's a little more complicated:

TODO: implement complete homepage migration for SourceForge. TODO: allow to suppress the automatic migration for SourceForge,

even if it is not about https vs. http.

func NewHomepageChecker

func NewHomepageChecker(value string, valueNoVar string, mkline *MkLine, mklines *MkLines) *HomepageChecker

func (*HomepageChecker) Check

func (ck *HomepageChecker) Check()

type Indentation

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

Indentation remembers the stack of preprocessing directives and their indentation. By convention, each directive is indented by 2 spaces. An excepting are multiple-inclusion guards, they don't increase the indentation.

Indentation starts with 0 spaces.
Each .if or .for indents all inner directives by 2.
Except for .if with multiple-inclusion guard, which indents all inner directives by 0.
Each .elif, .else, .endif, .endfor uses the outer indentation instead.

func NewIndentation

func NewIndentation() *Indentation

func (*Indentation) AddCheckedFile

func (ind *Indentation) AddCheckedFile(filename PkgsrcPath)

func (*Indentation) AddVar

func (ind *Indentation) AddVar(varname string)

AddVar remembers that the current indentation depends on the given variable, most probably because that variable is used in a .if directive.

Variables named *_MK are ignored since they are usually not interesting.

func (*Indentation) Args

func (ind *Indentation) Args() (string, *MkLine)

Args returns the arguments of the innermost .if, .elif or .for.

func (*Indentation) CheckFinish

func (ind *Indentation) CheckFinish(filename CurrPath)

func (*Indentation) DependsOn

func (ind *Indentation) DependsOn(varname string) bool

func (*Indentation) Depth

func (ind *Indentation) Depth(directive string) int

Depth returns the number of space characters by which the directive should be indented.

This is typically two more than the surrounding level, except for multiple-inclusion guards.

func (*Indentation) HasExists

func (ind *Indentation) HasExists(filename PkgsrcPath) bool

HasExists returns whether the given filename has been tested in an exists(filename) condition and thus may or may not exist.

func (*Indentation) IsConditional

func (ind *Indentation) IsConditional() bool

IsConditional returns whether the current line depends on evaluating any .if or .elif expression, or is inside a .for loop.

Variables named *_MK are excluded since they are usually not interesting.

func (*Indentation) IsEmpty

func (ind *Indentation) IsEmpty() bool

func (*Indentation) Pop

func (ind *Indentation) Pop()

func (*Indentation) Push

func (ind *Indentation) Push(mkline *MkLine, indent int, args string, guard bool)

func (*Indentation) RememberUsedVariables

func (ind *Indentation) RememberUsedVariables(cond *MkCond)

func (*Indentation) String

func (ind *Indentation) String() string

func (*Indentation) TrackAfter

func (ind *Indentation) TrackAfter(mkline *MkLine)

func (*Indentation) TrackBefore

func (ind *Indentation) TrackBefore(mkline *MkLine)

func (*Indentation) Varnames

func (ind *Indentation) Varnames() []string

Varnames returns the list of all variables that are mentioned in any condition or loop surrounding the current line.

Variables named *_MK are excluded since they are usually not interesting.

type InterPackage

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

func (*InterPackage) Bl3

func (ip *InterPackage) Bl3(name string, loc *Location) *Location

Bl3 remembers that the given buildlink3 name is used at the given location. Since these names must be unique, there should be no other location where the same name is used.

func (*InterPackage) Enable

func (ip *InterPackage) Enable()

func (*InterPackage) Enabled

func (ip *InterPackage) Enabled() bool

func (*InterPackage) Hash

func (ip *InterPackage) Hash(alg string, filename RelPath, hashBytes []byte, loc *Location) *Hash

func (*InterPackage) IsLicenseUsed

func (ip *InterPackage) IsLicenseUsed(name string) bool

func (*InterPackage) UseLicense

func (ip *InterPackage) UseLicense(name string)

type LazyStringBuilder

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

LazyStringBuilder builds a string that is most probably equal to an already existing string. In that case, it avoids any memory allocations.

func NewLazyStringBuilder

func NewLazyStringBuilder(expected string) LazyStringBuilder

func (*LazyStringBuilder) Len

func (b *LazyStringBuilder) Len() int

func (*LazyStringBuilder) Reset

func (b *LazyStringBuilder) Reset(expected string)

func (*LazyStringBuilder) String

func (b *LazyStringBuilder) String() string

func (*LazyStringBuilder) Write

func (b *LazyStringBuilder) Write(p []byte) (n int, err error)

func (*LazyStringBuilder) WriteByte

func (b *LazyStringBuilder) WriteByte(c byte)

func (*LazyStringBuilder) WriteString

func (b *LazyStringBuilder) WriteString(s string)

type LicenseChecker

type LicenseChecker struct {
	MkLines *MkLines
	MkLine  *MkLine
}

func (*LicenseChecker) Check

func (lc *LicenseChecker) Check(value string, op MkOperator)

type Line

type Line struct {
	Location Location
	Basename RelPath // the last component of the Filename

	// the text of the line, without the trailing newline character;
	// in Makefiles, also contains the text from the continuation lines,
	// joined by single spaces
	Text string
	// contains filtered or unexported fields
}

Line represents a line of text from a file.

func NewLine

func NewLine(filename CurrPath, lineno int, text string, rawLine *RawLine) *Line

func NewLineEOF

func NewLineEOF(filename CurrPath) *Line

NewLineEOF creates a dummy line for logging, with the "line number" EOF.

func NewLineMulti

func NewLineMulti(filename CurrPath, firstLine int, text string, rawLines []*RawLine) *Line

NewLineMulti is for logical Makefile lines that end with backslash.

func NewLineWhole

func NewLineWhole(filename CurrPath) *Line

NewLineWhole creates a dummy line for logging messages that affect a file as a whole.

func (*Line) Autofix

func (line *Line) Autofix() *Autofix

Autofix returns the autofix instance belonging to the line.

Usage:

fix := line.Autofix()

fix.Errorf("Must not be ...")
fix.Warnf("Should not be ...")
fix.Notef("It is also possible ...")

fix.Explain(
    "Explanation ...",
    "... end of explanation.")

fix.Replace("from", "to")
fix.ReplaceAfter("prefix", "from", "to")
fix.InsertAbove("new line")
fix.InsertBelow("new line")
fix.Delete()
fix.Custom(func(showAutofix, autofix bool) {})

fix.Apply()

func (*Line) Errorf

func (line *Line) Errorf(format string, args ...interface{})

func (*Line) Explain

func (line *Line) Explain(explanation ...string)

func (*Line) File

func (line *Line) File(rel RelPath) CurrPath

File resolves the given path relative to the directory where this line appears in.

func (*Line) Filename

func (line *Line) Filename() CurrPath

func (*Line) IsCvsID

func (line *Line) IsCvsID(prefixRe regex.Pattern) (found bool, expanded bool)

func (*Line) IsMultiline

func (line *Line) IsMultiline() bool

func (*Line) Linenos

func (line *Line) Linenos() string

func (*Line) Notef

func (line *Line) Notef(format string, args ...interface{})

func (*Line) RawText

func (line *Line) RawText(rawIndex int) string

RawText returns the raw text from the given physical line, excluding \n, including any previous autofixes.

func (*Line) Rel

func (line *Line) Rel(other CurrPath) RelPath

Rel returns the relative path from this line to the given file path. This is typically used for arguments in diagnostics, which should always be relative to the line with which the diagnostic is associated.

func (*Line) RelLine

func (line *Line) RelLine(other *Line) string

RelLine returns a reference to another line, which can be in the same file or in a different file.

func (*Line) RelLocation

func (line *Line) RelLocation(other Location) string

func (*Line) String

func (line *Line) String() string

func (*Line) Warnf

func (line *Line) Warnf(format string, args ...interface{})

type LineChecker

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

func (LineChecker) CheckLength

func (ck LineChecker) CheckLength(maxLength int)

func (LineChecker) CheckTrailingWhitespace

func (ck LineChecker) CheckTrailingWhitespace()

func (LineChecker) CheckValidCharacters

func (ck LineChecker) CheckValidCharacters()

type Lines

type Lines struct {
	Filename CurrPath
	BaseName RelPath
	Lines    []*Line
}

func Load

func Load(filename CurrPath, options LoadOptions) *Lines

func NewLines

func NewLines(filename CurrPath, lines []*Line) *Lines

func (*Lines) CheckCvsID

func (ls *Lines) CheckCvsID(index int, prefixRe regex.Pattern, suggestedPrefix string) bool

CheckCvsID returns true if the expected CVS Id was found.

func (*Lines) EOFLine

func (ls *Lines) EOFLine() *Line

func (*Lines) LastLine

func (ls *Lines) LastLine() *Line

func (*Lines) Len

func (ls *Lines) Len() int

func (*Lines) SaveAutofixChanges

func (ls *Lines) SaveAutofixChanges() bool

func (*Lines) Whole

func (ls *Lines) Whole() *Line

Whole returns a virtual line that can be used for issuing diagnostics and explanations, but not for text replacements.

type LinesLexer

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

LinesLexer records the state when checking a list of lines from top to bottom.

func NewLinesLexer

func NewLinesLexer(lines *Lines) *LinesLexer

func (*LinesLexer) CurrentLine

func (llex *LinesLexer) CurrentLine() *Line

CurrentLine returns the line that the lexer is currently looking at. For the EOF, a virtual line with line number "EOF" is returned.

func (*LinesLexer) EOF

func (llex *LinesLexer) EOF() bool

func (*LinesLexer) NextRegexp

func (llex *LinesLexer) NextRegexp(re regex.Pattern) []string

func (*LinesLexer) PreviousLine

func (llex *LinesLexer) PreviousLine() *Line

func (*LinesLexer) Skip

func (llex *LinesLexer) Skip() bool

Skip skips the current line.

func (*LinesLexer) SkipEmptyOrNote

func (llex *LinesLexer) SkipEmptyOrNote() bool

func (*LinesLexer) SkipPrefix

func (llex *LinesLexer) SkipPrefix(prefix string) bool

func (*LinesLexer) SkipRegexp

func (llex *LinesLexer) SkipRegexp(re regex.Pattern) bool

func (*LinesLexer) SkipText

func (llex *LinesLexer) SkipText(text string) bool

func (*LinesLexer) SkipTextOrWarn

func (llex *LinesLexer) SkipTextOrWarn(text string) bool

func (*LinesLexer) Undo

func (llex *LinesLexer) Undo()

type LoadOptions

type LoadOptions uint8
const (
	MustSucceed LoadOptions = 1 << iota // It's a fatal error if loading fails.
	NotEmpty                            // It is an error if the file is empty.
	Makefile                            // Lines ending in a backslash are continued in the next line.
	LogErrors                           //
)

type Location

type Location struct {
	Filename CurrPath
	// contains filtered or unexported fields
}

func NewLocation

func NewLocation(filename CurrPath, lineno int) Location

func (*Location) File

func (loc *Location) File(rel RelPath) CurrPath

File resolves the given path relative to the directory of this location.

func (*Location) Lineno

func (loc *Location) Lineno(rawIndex int) int

type LogLevel

type LogLevel struct {
	TraditionalName string
	GccName         string
}

type Logger

type Logger struct {
	Opts LoggerOpts
	// contains filtered or unexported fields
}

func (*Logger) Diag

func (l *Logger) Diag(line *Line, level *LogLevel, format string, args ...interface{})

Diag logs a diagnostic. These are filtered by the --only command line option, and duplicates are suppressed unless the --log-verbose command line option is given.

See Logf for logging arbitrary messages.

func (*Logger) Explain

func (l *Logger) Explain(explanation ...string)

Explain outputs an explanation for the preceding diagnostic if the --explain option is given. Otherwise it just records that an explanation is available.

func (*Logger) FirstTime

func (l *Logger) FirstTime(filename CurrPath, linenos, msg string) bool

func (*Logger) IsAutofix

func (l *Logger) IsAutofix() bool

IsAutofix returns whether one of the --show-autofix or --autofix options is active.

func (*Logger) Logf

func (l *Logger) Logf(level *LogLevel, filename CurrPath, lineno, format, msg string)

func (*Logger) Relevant

func (l *Logger) Relevant(format string) bool

Relevant decides and remembers whether the given diagnostic is relevant and should be logged.

The result of the decision affects all log items until Relevant is called for the next time.

func (*Logger) ShowSummary

func (l *Logger) ShowSummary(args []string)

func (*Logger) TechErrorf

func (l *Logger) TechErrorf(location CurrPath, format string, args ...interface{})

TechErrorf logs a technical error on the error output.

For diagnostics, use Logf instead.

func (*Logger) TechFatalf

func (l *Logger) TechFatalf(location CurrPath, format string, args ...interface{})

TechFatalf logs a technical error on the error output and quits pkglint.

For diagnostics, use Logf instead.

type LoggerOpts

type LoggerOpts struct {
	ShowAutofix,
	Autofix,
	Explain,
	ShowSource,
	GccOutput,
	Quiet bool

	Only []string
}

type MkAssignChecker

type MkAssignChecker struct {
	MkLine  *MkLine
	MkLines *MkLines
}

MkAssignChecker checks a variable assignment line in a Makefile.

func NewMkAssignChecker

func NewMkAssignChecker(mkLine *MkLine, mkLines *MkLines) *MkAssignChecker

type MkCond

type MkCond struct {
	Or  []*MkCond
	And []*MkCond
	Not *MkCond

	Defined string
	Empty   *MkVarUse
	Term    *MkCondTerm
	Compare *MkCondCompare
	Call    *MkCondCall
	Paren   *MkCond
}

MkCond is a condition in a Makefile, such as ${OPSYS} == NetBSD.

The representation is somewhere between syntactic and semantic. Unnecessary parentheses are omitted in this representation, but !empty(VARNAME) is represented differently from ${VARNAME} != "". For higher level analysis, a unified representation might be better.

func (*MkCond) Walk

func (cond *MkCond) Walk(callback *MkCondCallback)

type MkCondCall

type MkCondCall struct {
	Name string
	Arg  string
}

type MkCondCallback

type MkCondCallback struct {
	And     func(conds []*MkCond)
	Not     func(cond *MkCond)
	Defined func(varname string)
	Empty   func(empty *MkVarUse)
	Compare func(left *MkCondTerm, op string, right *MkCondTerm)
	Call    func(name string, arg string)
	Paren   func(cond *MkCond)

	// Var is called for every atomic expression that consists solely
	// of a variable use, possibly enclosed in double quotes, but without
	// any surrounding string literal parts.
	Var func(varuse *MkVarUse)

	// VarUse is called for each variable that is used in some expression.
	VarUse func(varuse *MkVarUse)
}

MkCondCallback defines the actions for walking a Makefile condition using MkCondWalker.Walk.

type MkCondChecker

type MkCondChecker struct {
	MkLine  *MkLine
	MkLines *MkLines
}

MkCondChecker checks conditions in Makefiles. These conditions occur in .if and .elif clauses, as well as the :? modifier.

func NewMkCondChecker

func NewMkCondChecker(mkLine *MkLine, mkLines *MkLines) *MkCondChecker

func (*MkCondChecker) Check

func (ck *MkCondChecker) Check()

type MkCondCompare

type MkCondCompare struct {
	Left MkCondTerm
	// For numeric comparison: one of <, <=, ==, !=, >=, >.
	//
	// For string comparison: one of ==, !=.
	//
	// For not-empty test: "".
	Op    string
	Right MkCondTerm
}

type MkCondTerm

type MkCondTerm struct {
	Str string
	Num string
	Var *MkVarUse
}

type MkCondWalker

type MkCondWalker struct{}

func (*MkCondWalker) Walk

func (w *MkCondWalker) Walk(cond *MkCond, callback *MkCondCallback)

type MkLexer

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

MkLexer splits a text into a sequence of variable uses and plain text.

The actual parsing algorithm in devel/bmake/files/var.c differs from pkglint's parser in many ways and produces different results in almost all edge cases. See devel/bmake/files/var.c:/'\\\\'/.

The pkglint parser had been built from scratch using naive assumptions about how bmake parses these expressions. These assumptions do not hold a strict test, but luckily the pkgsrc package developers don't explore these edge cases anyway.

func NewMkLexer

func NewMkLexer(text string, diag Autofixer) *MkLexer

func (*MkLexer) Autofix

func (p *MkLexer) Autofix() *Autofix

Autofix must only be called if HasDiag returns true.

func (*MkLexer) EOF

func (p *MkLexer) EOF() bool

func (*MkLexer) Errorf

func (p *MkLexer) Errorf(format string, args ...interface{})

func (*MkLexer) Explain

func (p *MkLexer) Explain(explanation ...string)

func (*MkLexer) HasDiag

func (p *MkLexer) HasDiag() bool

func (*MkLexer) MkToken

func (p *MkLexer) MkToken() *MkToken

func (*MkLexer) MkTokens

func (p *MkLexer) MkTokens() ([]*MkToken, string)

MkTokens splits a text like in the following example:

Text${VAR:Mmodifier}${VAR2}more text${VAR3}

into tokens like these:

Text
${VAR:Mmodifier}
${VAR2}
more text
${VAR3}

func (*MkLexer) Notef

func (p *MkLexer) Notef(format string, args ...interface{})

func (*MkLexer) Rest

func (p *MkLexer) Rest() string

func (*MkLexer) VarUse

func (p *MkLexer) VarUse() *MkVarUse

VarUse parses a variable expression like ${VAR}, $@, ${VAR:Mpattern:Ox}.

func (*MkLexer) VarUseModifiers

func (p *MkLexer) VarUseModifiers(varname string, closing byte) []MkVarUseModifier

VarUseModifiers parses the modifiers of a variable being used, such as :Q, :Mpattern.

See the bmake manual page.

func (*MkLexer) Varname

func (p *MkLexer) Varname() string

func (*MkLexer) Warnf

func (p *MkLexer) Warnf(format string, args ...interface{})

type MkLine

type MkLine struct {
	*Line
	// contains filtered or unexported fields
}

MkLine is a line from a Makefile fragment. There are several types of lines. The most common types in pkgsrc are variable assignments, shell commands and directives like .if and .for.

func (*MkLine) Args

func (mkline *MkLine) Args() string

Args returns the arguments from an .if, .ifdef, .ifndef, .elif, .for, .undef.

func (*MkLine) Comment

func (mkline *MkLine) Comment() string

Comment returns the comment after the first unescaped #.

A special case are variable assignments. If these are commented out entirely, they still count as variable assignments, which means that their comment is the one after the value, if any.

Shell commands (lines that start with a tab) cannot have comments, as the # characters are passed uninterpreted to the shell.

Example:

VAR=value # comment

In the above line, the comment is " comment", including the leading space.

func (*MkLine) Cond

func (mkline *MkLine) Cond() *MkCond

Cond applies to an .if or .elif line and returns the parsed condition.

If a parse error occurs, it is silently swallowed, returning a best-effort part of the condition, or even nil.

func (*MkLine) ConditionalVars

func (mkline *MkLine) ConditionalVars() []string

ConditionalVars applies to .include lines and contains the variable names on which the inclusion depends.

It is initialized later, step by step, when parsing other lines.

func (*MkLine) Directive

func (mkline *MkLine) Directive() string

Directive returns the preprocessing directive, like "if", "for", "endfor", etc.

See matchMkDirective.

func (*MkLine) DirectiveComment

func (mkline *MkLine) DirectiveComment() string

DirectiveComment is the trailing end-of-line comment, typically at a deeply nested .endif or .endfor.

func (*MkLine) ExplainRelativeDirs

func (mkline *MkLine) ExplainRelativeDirs()

func (*MkLine) Fields

func (mkline *MkLine) Fields() []string

Fields applies to variable assignments and .for loops. For variable assignments, it returns the right-hand side, properly split into words. For .for loops, it returns all arguments (including variable names), properly split into words.

func (*MkLine) FirstLineContainsValue

func (mkline *MkLine) FirstLineContainsValue() bool

FirstLineContainsValue returns whether the variable assignment of a multiline contains a textual value in the first line.

VALUE_IN_FIRST_LINE= value \
        starts in first line
NO_VALUE_IN_FIRST_LINE= \
        value starts in second line

func (*MkLine) ForEachUsed

func (mkline *MkLine) ForEachUsed(action func(varUse *MkVarUse, time VucTime))

ForEachUsed calls the action for each variable that is used in the line.

func (*MkLine) ForEachUsedText

func (mkline *MkLine) ForEachUsedText(text string, time VucTime, action func(varUse *MkVarUse, time VucTime))

func (*MkLine) ForEachUsedVarUse

func (mkline *MkLine) ForEachUsedVarUse(varuse *MkVarUse, time VucTime, action func(varUse *MkVarUse, time VucTime))

func (*MkLine) HasComment

func (mkline *MkLine) HasComment() bool

func (*MkLine) HasElseBranch

func (mkline *MkLine) HasElseBranch() bool

func (*MkLine) HasRationale

func (mkline *MkLine) HasRationale(keywords ...string) bool

HasRationale returns true if the comments that are close enough to this line contain a rationale for suppressing a diagnostic.

These comments are used to suppress pkglint warnings, such as for BROKEN, NOT_FOR_PLATFORMS, MAKE_JOBS_SAFE, and HOMEPAGE using http instead of https.

To qualify as a rationale, the comment must contain any of the given keywords. If no keywords are given, any comment qualifies.

func (*MkLine) IncludedFile

func (mkline *MkLine) IncludedFile() RelPath

func (*MkLine) IncludedFileFull

func (mkline *MkLine) IncludedFileFull() CurrPath

IncludedFileFull returns the path to the included file.

func (*MkLine) Indent

func (mkline *MkLine) Indent() string

Indent returns the whitespace between the dot and the directive.

For the following example line it returns two spaces:

.  include "other.mk"

func (*MkLine) IsComment

func (mkline *MkLine) IsComment() bool

IsComment returns true for lines that consist entirely of a comment.

func (*MkLine) IsCommentedVarassign

func (mkline *MkLine) IsCommentedVarassign() bool

IsCommentedVarassign returns true for commented-out variable assignments. In most cases these are treated as ordinary comments, but in some others they are treated like variable assignments, just inactive ones.

To qualify as a commented variable assignment, there must be no space between the # and the variable name.

Example:

#VAR=   value

Counterexample:

# VAR=  value

func (*MkLine) IsDependency

func (mkline *MkLine) IsDependency() bool

IsDependency returns true for dependency lines like "target: source".

func (*MkLine) IsDirective

func (mkline *MkLine) IsDirective() bool

IsDirective returns true for conditionals (.if/.elif/.else/.if) or loops (.for/.endfor).

See IsInclude.

func (*MkLine) IsEmpty

func (mkline *MkLine) IsEmpty() bool

func (*MkLine) IsInclude

func (mkline *MkLine) IsInclude() bool

IsInclude returns true for lines like: .include "other.mk"

See IsSysinclude for lines like: .include <sys.mk>

func (*MkLine) IsShellCommand

func (mkline *MkLine) IsShellCommand() bool

IsShellCommand returns true for tab-indented lines that are assigned to a Make target. Example:

pre-configure:    # IsDependency
        ${ECHO}   # IsShellCommand

func (*MkLine) IsSysinclude

func (mkline *MkLine) IsSysinclude() bool

IsSysinclude returns true for lines like: .include <sys.mk>

See IsInclude for lines like: .include "other.mk"

func (*MkLine) IsVarassign

func (mkline *MkLine) IsVarassign() bool

IsVarassign returns true for variable assignments of the form VAR=value.

See IsCommentedVarassign.

func (*MkLine) IsVarassignMaybeCommented

func (mkline *MkLine) IsVarassignMaybeCommented() bool

IsVarassignMaybeCommented returns true for variable assignments of the form VAR=value, no matter if they are commented out like #VAR=value or not. To qualify as a commented variable assignment, there must be no space between the # and the variable name.

Example:

#VAR=   value

Counterexample:

# VAR=  value

func (*MkLine) MustExist

func (mkline *MkLine) MustExist() bool

func (*MkLine) NeedsCond

func (mkline *MkLine) NeedsCond() bool

NeedsCond returns whether the directive requires a condition as argument.

func (*MkLine) Op

func (mkline *MkLine) Op() MkOperator

Op applies to variable assignments and returns the assignment operator.

func (*MkLine) RelMkLine

func (mkline *MkLine) RelMkLine(other *MkLine) string

RelMkLine returns a reference to another line, which can be in the same file or in a different file.

If there is a type mismatch when calling this function, try to add ".line" to either the method receiver or the other line.

func (*MkLine) ResolveVarsInRelativePath

func (mkline *MkLine) ResolveVarsInRelativePath(relativePath PackagePath, pkg *Package) PackagePath

func (*MkLine) SetConditionalVars

func (mkline *MkLine) SetConditionalVars(varnames []string)

func (*MkLine) SetHasElseBranch

func (mkline *MkLine) SetHasElseBranch(elseLine *MkLine)

func (*MkLine) ShellCommand

func (mkline *MkLine) ShellCommand() string

func (*MkLine) Sources

func (mkline *MkLine) Sources() string

func (*MkLine) String

func (mkline *MkLine) String() string

String returns the filename and line numbers.

func (*MkLine) Targets

func (mkline *MkLine) Targets() string

func (*MkLine) Tokenize

func (mkline *MkLine) Tokenize(text string, warn bool) []*MkToken

Tokenize extracts variable uses and other text from the given text.

When used in IsVarassign lines, the given text must have the format after stripping the end-of-line comment. Such text is available from Value. A shell comment is therefore marked by a simple #, not an escaped \# like in Makefiles.

When used in IsShellCommand lines, # does not mark a Makefile comment and may thus still appear in the text. Therefore, # marks a shell comment.

Example:

input:  ${PREFIX}/bin abc
output: [MkToken("${PREFIX}", MkVarUse("PREFIX")), MkToken("/bin abc")]

See ValueTokens, which is the tokenized version of Value.

func (*MkLine) UnquoteShell

func (mkline *MkLine) UnquoteShell(str string, warn bool) string

UnquoteShell removes one level of double and single quotes, like in the shell.

See ValueFields.

func (*MkLine) Value

func (mkline *MkLine) Value() string

func (*MkLine) ValueAlign

func (mkline *MkLine) ValueAlign() string

ValueAlign applies to variable assignments and returns all the text to the left of the variable value, e.g. "VARNAME+=\t".

func (*MkLine) ValueFields

func (mkline *MkLine) ValueFields(value string) []string

ValueFields splits the given value in the same way as the :M variable modifier, taking care of variable references. Example:

ValueFields("${VAR:Udefault value} ${VAR2}two words;;; 'word three'")
=> "${VAR:Udefault value}"
   "${VAR2}two"
   "words;;;"
   "'word three'"

Note that even though the first word contains a space, it is not split at that point since the space is inside a variable use. Shell tokens such as semicolons are also treated as normal characters. Only double and single quotes are interpreted.

Compare devel/bmake/files/str.c, function brk_string.

See UnquoteShell.

func (*MkLine) ValueFieldsLiteral

func (mkline *MkLine) ValueFieldsLiteral() []string

func (*MkLine) ValueSplit

func (mkline *MkLine) ValueSplit(value string, separator string) []string

ValueSplit splits the given value, taking care of variable references. Example:

ValueSplit("${VAR:Udefault}::${VAR2}two:words", ":")
=> "${VAR:Udefault}"
   ""
   "${VAR2}two"
   "words"

Note that even though the first word contains a colon, it is not split at that point since the colon is inside a variable use.

When several separators are adjacent, this results in empty words in the output.

func (*MkLine) ValueTokens

func (mkline *MkLine) ValueTokens() ([]*MkToken, string)

func (*MkLine) Varcanon

func (mkline *MkLine) Varcanon() string

Varcanon applies to variable assignments and returns the canonicalized variable name for parameterized variables. Examples:

HOMEPAGE           => "HOMEPAGE"
SUBST_SED.anything => "SUBST_SED.*"
SUBST_SED.${param} => "SUBST_SED.*"

func (*MkLine) VariableNeedsQuoting

func (mkline *MkLine) VariableNeedsQuoting(mklines *MkLines, varuse *MkVarUse, vartype *Vartype, vuc *VarUseContext) (needsQuoting YesNoUnknown)

VariableNeedsQuoting determines whether the given variable needs the :Q modifier in the given context.

This decision depends on many factors, such as whether the type of the context is a list of things, whether the variable is a list, whether it can contain only safe characters, and so on.

func (*MkLine) Varname

func (mkline *MkLine) Varname() string

Varname applies to variable assignments and returns the name of the variable that is assigned or appended to.

Example:

VARNAME.${param}?=      value   # Varname is "VARNAME.${param}"

func (*MkLine) Varparam

func (mkline *MkLine) Varparam() string

Varparam applies to variable assignments and returns the parameter for parameterized variables. Examples:

HOMEPAGE           => ""
SUBST_SED.anything => "anything"
SUBST_SED.${param} => "${param}"

func (*MkLine) WithoutMakeVariables

func (*MkLine) WithoutMakeVariables(value string) string

type MkLineChecker

type MkLineChecker struct {
	MkLines *MkLines
	MkLine  *MkLine
}

MkLineChecker provides checks for a single line from a Makefile fragment.

func NewMkLineChecker

func NewMkLineChecker(mkLines *MkLines, mkLine *MkLine) MkLineChecker

func (MkLineChecker) Check

func (ck MkLineChecker) Check()

func (MkLineChecker) CheckRelativePath

func (ck MkLineChecker) CheckRelativePath(pp PackagePath, rel RelPath, mustExist bool)

CheckRelativePath checks a relative path that leads to the directory of another package or to a subdirectory thereof or a file within there.

func (MkLineChecker) CheckRelativePkgdir

func (ck MkLineChecker) CheckRelativePkgdir(rel RelPath, pkgdir PackagePath)

CheckRelativePkgdir checks a reference from one pkgsrc package to another. These references should always have the form ../../category/package.

When used in DEPENDS or similar variables, these directories could theoretically also be relative to the pkgsrc root, which would save a few keystrokes. This, however, is not implemented in pkgsrc and suggestions regarding this topic have not been made in the last two decades on the public mailing lists. While being a bit redundant, the current scheme works well.

When used in .include directives, the relative package directories must be written with the leading ../.. anyway, so the benefit might not be too big at all.

func (MkLineChecker) CheckVartypeBasic

func (ck MkLineChecker) CheckVartypeBasic(varname string, checker *BasicType, op MkOperator, value, comment string, guessed bool)

CheckVartypeBasic checks a single list element of the given type.

For some variables (like `BuildlinkDepth`), `op` influences the valid values. The `comment` parameter comes from a variable assignment, when a part of the line is commented out.

type MkLineParser

type MkLineParser struct{}

MkLineParser parses a line of text into the syntactical parts of a line in Makefiles.

func NewMkLineParser

func NewMkLineParser() MkLineParser

func (MkLineParser) MatchVarassign

func (p MkLineParser) MatchVarassign(line *Line, text string, splitResult *mkLineSplitResult) (bool, *mkLineAssign)

func (MkLineParser) Parse

func (p MkLineParser) Parse(line *Line) *MkLine

Parse parses the text of a Makefile line to see what kind of line it is: variable assignment, include, comment, etc.

See devel/bmake/parse.c:/^Parse_File/

type MkLines

type MkLines struct {
	Tools *Tools // Tools defined in file scope.
	// contains filtered or unexported fields
}

MkLines contains data for the Makefile (or *.mk) that is currently checked.

func LoadMk

func LoadMk(filename CurrPath, pkg *Package, options LoadOptions) *MkLines

func NewMkLines

func NewMkLines(lines *Lines, pkg *Package, extraScope *Scope) *MkLines

func (*MkLines) Check

func (mklines *MkLines) Check()

func (*MkLines) CheckUsedBy

func (mklines *MkLines) CheckUsedBy(relativeName PkgsrcPath)

CheckUsedBy checks that this file (a Makefile.common) has the given relativeName in one of the "# used by" comments at the beginning of the file.

func (*MkLines) EOFLine

func (mklines *MkLines) EOFLine() *MkLine

func (*MkLines) ExpandLoopVar

func (mklines *MkLines) ExpandLoopVar(varname string) []string

ExpandLoopVar searches the surrounding .for loops for the given variable and returns a slice containing all its values, fully expanded.

It can only be used during an active ForEach call.

func (*MkLines) ForEach

func (mklines *MkLines) ForEach(action func(mkline *MkLine))

ForEach calls the action for each line, until the action returns false. It keeps track of the indentation (see MkLines.indentation) and all conditional variables (see Indentation.IsConditional).

func (*MkLines) ForEachEnd

func (mklines *MkLines) ForEachEnd(action func(mkline *MkLine) bool, atEnd func(lastMkline *MkLine)) bool

ForEachEnd calls the action for each line, until the action returns false. It keeps track of the indentation and all conditional variables. At the end, atEnd is called with the last line as its argument.

func (*MkLines) IsUnreachable

func (mklines *MkLines) IsUnreachable(mkline *MkLine) bool

IsUnreachable determines whether the given line is unreachable because a condition on the way to that line is not satisfied. If unsure, returns false.

Only the current package and Makefile fragment are taken into account. The line might still be reachable by another pkgsrc package.

func (*MkLines) SaveAutofixChanges

func (mklines *MkLines) SaveAutofixChanges()

func (*MkLines) SplitToParagraphs

func (mklines *MkLines) SplitToParagraphs() []*Paragraph

func (*MkLines) UseVar

func (mklines *MkLines) UseVar(mkline *MkLine, varname string, time VucTime)

UseVar remembers that the given variable is used in the given line. This controls the "defined but not used" warning.

func (*MkLines) Whole

func (mklines *MkLines) Whole() *Line

Whole returns a virtual line that can be used for issuing diagnostics and explanations, but not for text replacements.

type MkLinesLexer

type MkLinesLexer struct {
	LinesLexer
	// contains filtered or unexported fields
}

MkLinesLexer records the state when checking a list of Makefile lines from top to bottom.

func NewMkLinesLexer

func NewMkLinesLexer(mklines *MkLines) *MkLinesLexer

func (*MkLinesLexer) CurrentMkLine

func (mlex *MkLinesLexer) CurrentMkLine() *MkLine

func (*MkLinesLexer) PreviousMkLine

func (mlex *MkLinesLexer) PreviousMkLine() *MkLine

func (*MkLinesLexer) SkipIf

func (mlex *MkLinesLexer) SkipIf(pred func(mkline *MkLine) bool) bool

type MkOperator

type MkOperator uint8

func NewMkOperator

func NewMkOperator(op string) MkOperator

func (MkOperator) String

func (op MkOperator) String() string

func (MkOperator) Time

func (op MkOperator) Time() VucTime

Time returns the time at which the right-hand side of the assignment is evaluated.

type MkParser

type MkParser struct {
	EmitWarnings bool
	// contains filtered or unexported fields
}

MkParser wraps a Parser and provides methods for parsing things related to Makefiles.

func NewMkParser

func NewMkParser(diag Autofixer, text string) *MkParser

NewMkParser creates a new parser for the given text.

If line is given, it is used for reporting parse errors and warnings. Otherwise parsing is silent.

The text argument is assumed to be after unescaping the # character, which means the # is a normal character and does not introduce a Makefile comment. For VarUse, this distinction is irrelevant.

func (*MkParser) DependencyPattern

func (p *MkParser) DependencyPattern() *DependencyPattern

DependencyPattern parses a dependency pattern like "pkg>=1<2" or "pkg-[0-9]*".

func (*MkParser) EOF

func (p *MkParser) EOF() bool

func (*MkParser) MkCond

func (p *MkParser) MkCond() *MkCond

MkCond parses a condition like ${OPSYS} == "NetBSD".

See devel/bmake/files/cond.c.

func (*MkParser) Op

func (p *MkParser) Op() (bool, MkOperator)

func (*MkParser) PkgbasePattern

func (p *MkParser) PkgbasePattern() string

func (*MkParser) Rest

func (p *MkParser) Rest() string

type MkShAndOr

type MkShAndOr struct {
	Pipes []*MkShPipeline
	Ops   []string // Each element is either "&&" or "||"
}

MkShAndOr is a group of commands that are connected with && or || conditions.

The operators && and || have the same precedence and are evaluated strictly from left to right.

Example:

cd $dir && echo "In $dir" || echo "Cannot cd into $dir"

func NewMkShAndOr

func NewMkShAndOr(pipeline *MkShPipeline) *MkShAndOr

func (*MkShAndOr) Add

func (andor *MkShAndOr) Add(op string, pipeline *MkShPipeline) *MkShAndOr

type MkShCase

type MkShCase struct {
	Word  *ShToken
	Cases []*MkShCaseItem
}

MkShCase is a "case" statement, including all its branches.

Example:

case $filename in *.c) echo "C source" ;; esac

type MkShCaseItem

type MkShCaseItem struct {
	Patterns  []*ShToken
	Action    *MkShList
	Separator MkShSeparator
	Var       *ShToken // ${PATTERNS:@p@ (${p}) action ;; @}
}

MkShCaseItem is one branch of a "case" statement.

Example:

*.c) echo "C source" ;;

type MkShCommand

type MkShCommand struct {
	Simple    *MkShSimpleCommand
	Compound  *MkShCompoundCommand
	FuncDef   *MkShFunctionDefinition
	Redirects []*MkShRedirection // For Compound and FuncDef
}

MkShCommand is a simple or compound shell command.

Examples:

LC_ALL=C sort */*.c > sorted
dir() { ls -l "$@"; }
{ echo "first"; echo "second"; }

type MkShCompoundCommand

type MkShCompoundCommand struct {
	Brace    *MkShList
	Subshell *MkShList
	For      *MkShFor
	Case     *MkShCase
	If       *MkShIf
	Loop     *MkShLoop
}

MkShCompoundCommand is a group of commands.

Examples:

{ echo "first"; echo "second"; }
for f in *.c; do compile "$f"; done
if [ -f "$file" ]; then echo "It exists"; fi
while sleep 1; do printf .; done

type MkShFor

type MkShFor struct {
	Varname string
	Values  []*ShToken
	Body    *MkShList
}

MkShFor is a "for" loop.

Example:

for f in *.c; do compile "$f"; done

type MkShFunctionDefinition

type MkShFunctionDefinition struct {
	Name string
	Body *MkShCompoundCommand
}

MkShFunctionDefinition is the definition of a shell function.

Example:

dir() { ls -l "$@"; }

type MkShIf

type MkShIf struct {
	Conds   []*MkShList
	Actions []*MkShList
	Else    *MkShList
}

MkShIf is a conditional statement, possibly having many branches.

Example:

if [ -f "$file" ]; then echo "It exists"; fi

func (*MkShIf) Prepend

func (cl *MkShIf) Prepend(cond *MkShList, action *MkShList)

type MkShList

type MkShList struct {
	AndOrs []*MkShAndOr

	// The separators after each AndOr.
	// There may be one less entry than in AndOrs.
	Separators []MkShSeparator
}

MkShList is a list of shell commands, separated by newlines or semicolons.

Example:

cd $dir && echo "In $dir"; cd ..; ls -l

func NewMkShList

func NewMkShList() *MkShList

func (*MkShList) AddAndOr

func (list *MkShList) AddAndOr(andor *MkShAndOr) *MkShList

func (*MkShList) AddSeparator

func (list *MkShList) AddSeparator(separator MkShSeparator) *MkShList

type MkShLoop

type MkShLoop struct {
	Cond   *MkShList
	Action *MkShList
	Until  bool
}

MkShLoop is a "while" or "until" loop.

Example:

while sleep 1; do printf .; done

type MkShPipeline

type MkShPipeline struct {
	Negated bool
	Cmds    []*MkShCommand
}

MkShPipeline is a group of commands, connected by pipelines.

Example: grep word file | sed s,^,---,

func NewMkShPipeline

func NewMkShPipeline(negated bool, cmds []*MkShCommand) *MkShPipeline

func (*MkShPipeline) Add

func (pipe *MkShPipeline) Add(cmd *MkShCommand) *MkShPipeline

type MkShRedirection

type MkShRedirection struct {
	Fd     int      // Or -1
	Op     string   // See io_file in shell.y for possible values
	Target *ShToken // The filename or &fd
}

MkShRedirection is a single file descriptor redirection.

Examples:

> sorted
2>&1

type MkShSeparator

type MkShSeparator uint8

MkShSeparator is one of ; & newline.

type MkShSimpleCommand

type MkShSimpleCommand struct {
	Assignments  []*ShToken
	Name         *ShToken
	Args         []*ShToken
	Redirections []*MkShRedirection
}

MkShSimpleCommand is a shell command that does not involve any pipeline or conditionals.

Example:

LC_ALL=C sort */*.c > sorted

type MkShWalker

type MkShWalker struct {
	Callback struct {
		List               func(list *MkShList)
		AndOr              func(andor *MkShAndOr)
		Pipeline           func(pipeline *MkShPipeline)
		Command            func(command *MkShCommand)
		SimpleCommand      func(command *MkShSimpleCommand)
		CompoundCommand    func(command *MkShCompoundCommand)
		Case               func(caseClause *MkShCase)
		CaseItem           func(caseItem *MkShCaseItem)
		FunctionDefinition func(funcdef *MkShFunctionDefinition)
		If                 func(ifClause *MkShIf)
		Loop               func(loop *MkShLoop)
		Words              func(words []*ShToken)
		Word               func(word *ShToken)
		Redirects          func(redirects []*MkShRedirection)
		Redirect           func(redirect *MkShRedirection)
		For                func(forClause *MkShFor)

		// For variable definition in a for loop.
		Varname func(varname string)
	}

	// Context[0] is the currently visited element,
	// Context[1] is its immediate parent element, and so on.
	// This is useful when the check for a CaseItem needs to look at the enclosing Case.
	Context []MkShWalkerPathElement
}

func NewMkShWalker

func NewMkShWalker() *MkShWalker

func (*MkShWalker) Current

func (w *MkShWalker) Current() MkShWalkerPathElement

Current provides access to the element that the walker is currently processing, especially its index as seen from its parent element.

func (*MkShWalker) Parent

func (w *MkShWalker) Parent(steps int) interface{}

Parent returns an ancestor element from the currently visited path. Parent(0) is the element that is currently visited, Parent(1) is its direct parent, and so on.

func (*MkShWalker) Walk

func (w *MkShWalker) Walk(list *MkShList)

Walk calls the given callback for each node of the parsed shell program, in visiting order from large to small.

type MkShWalkerPathElement

type MkShWalkerPathElement struct {

	// For fields that can be repeated, this is the index as seen from the parent element.
	// For fields that cannot be repeated, it is -1.
	//
	// For example, in the SimpleCommand "var=value cmd arg1 arg2",
	// there are multiple child elements of type Words.
	//
	// The first Words are the variable assignments, which have index 0.
	//
	// The command "cmd" has type Word, therefore it cannot be confused
	// with either of the Words lists and has index -1.
	//
	// The second Words are the arguments, which have index 1.
	// In this example, there are two arguments, so when visiting the
	// arguments individually, arg1 will have index 0 and arg2 will have index 1.
	//
	// TODO: It might be worth defining negative indexes to correspond
	//  to the fields "Cond", "Action", "Else", etc.
	Index int

	Element interface{}
}

type MkToken

type MkToken struct {
	Text   string    // Used for both literal text and variable uses
	Varuse *MkVarUse // For literal text, it is nil
}

MkToken represents a contiguous string from a Makefile. It is either a literal string or a variable use.

Example: /usr/share/${PKGNAME}/data consists of 3 tokens:

  1. MkToken{Text: "/usr/share/"}
  2. MkToken{Text: "${PKGNAME}", Varuse: NewMkVarUse("PKGNAME")}
  3. MkToken{Text: "/data"}

type MkTokensLexer

type MkTokensLexer struct {
	// The lexer for the current text-only token.
	// If the current token is a variable use, the lexer will always return
	// EOF internally. That is not visible from the outside though, as EOF is
	// overridden in this type.
	*textproc.Lexer
	// contains filtered or unexported fields
}

MkTokensLexer parses a sequence of variable uses (like ${VAR:Mpattern}) interleaved with other text that is uninterpreted by bmake.

func NewMkTokensLexer

func NewMkTokensLexer(tokens []*MkToken) *MkTokensLexer

func (*MkTokensLexer) EOF

func (m *MkTokensLexer) EOF() bool

EOF returns whether the whole input has been consumed.

func (*MkTokensLexer) Mark

func (m *MkTokensLexer) Mark() MkTokensLexerMark

Mark remembers the current position of the lexer. The lexer can later be reset to that position by calling Reset.

func (*MkTokensLexer) NextVarUse

func (m *MkTokensLexer) NextVarUse() *MkToken

NextVarUse returns the next varuse token, unless there is some plain text before it. In that case or at EOF, it returns nil.

func (*MkTokensLexer) Reset

func (m *MkTokensLexer) Reset(mark MkTokensLexerMark)

Reset sets the lexer back to the given position. The lexer may be reset to the same mark multiple times, that is, the mark is not destroyed.

func (*MkTokensLexer) Rest

func (m *MkTokensLexer) Rest() string

Rest returns the string concatenation of the tokens that have not yet been consumed.

func (*MkTokensLexer) Since

func (m *MkTokensLexer) Since(mark MkTokensLexerMark) string

Since returns the text between the given mark and the current position of the lexer.

func (*MkTokensLexer) Skip

func (m *MkTokensLexer) Skip(n int) bool

Skip skips the next n bytes from the plain text. If there is a variable use in the next n bytes, it panics; see SkipMixed.

func (*MkTokensLexer) SkipMixed

func (m *MkTokensLexer) SkipMixed(n int) bool

SkipMixed skips the next n bytes, be they in plain text or in variable uses. It is only used in very special situations.

type MkTokensLexerMark

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

MkTokensLexerMark remembers a position of a token lexer, to be restored later.

type MkVarUse

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

MkVarUse represents a reference to a Make variable, with optional modifiers.

For nested variable expressions, the variable name can contain references to other variables. For example, ${TOOLS.${t}} is a MkVarUse with varname "TOOLS.${t}" and no modifiers.

Example: ${PKGNAME}

Example: ${PKGNAME:S/from/to/}

func NewMkVarUse

func NewMkVarUse(varname string, modifiers ...MkVarUseModifier) *MkVarUse

func ToVarUse

func ToVarUse(str string) *MkVarUse

ToVarUse converts the given string into a MkVarUse, or returns nil if there is a parse error or some trailing text. Parse errors are silently ignored.

func (*MkVarUse) HasModifier

func (vu *MkVarUse) HasModifier(prefix string) bool

func (*MkVarUse) IsExpression

func (vu *MkVarUse) IsExpression() bool

IsExpression returns whether the varname is interpreted as an expression instead of a variable name (rare, only the modifiers :? and :L do this).

func (*MkVarUse) IsQ

func (vu *MkVarUse) IsQ() bool

func (*MkVarUse) Mod

func (vu *MkVarUse) Mod() string

func (*MkVarUse) String

func (vu *MkVarUse) String() string

type MkVarUseChecker

type MkVarUseChecker struct {
	MkLines *MkLines
	MkLine  *MkLine
	// contains filtered or unexported fields
}

func NewMkVarUseChecker

func NewMkVarUseChecker(use *MkVarUse, mklines *MkLines, mkline *MkLine) *MkVarUseChecker

func (*MkVarUseChecker) Check

func (ck *MkVarUseChecker) Check(vuc *VarUseContext)

CheckVaruse checks a single use of a variable in a specific context.

type MkVarUseModifier

type MkVarUseModifier string

MkVarUseModifier stores the text of the modifier, without the initial colon. Examples: "Q", "S,from,to,g"

func (MkVarUseModifier) ChangesList

func (m MkVarUseModifier) ChangesList() bool

ChangesList returns true if applying this modifier to a variable may change the expression from a list type to a non-list type or vice versa.

func (MkVarUseModifier) EvalSubst

func (MkVarUseModifier) EvalSubst(s string, left bool, from string, right bool, to string, flags string) (ok bool, result string)

mkopSubst evaluates make(1)'s :S substitution operator. It does not resolve any variables.

func (MkVarUseModifier) HasPrefix

func (m MkVarUseModifier) HasPrefix(prefix string) bool

func (MkVarUseModifier) IsQ

func (m MkVarUseModifier) IsQ() bool

func (MkVarUseModifier) IsSuffixSubst

func (m MkVarUseModifier) IsSuffixSubst() bool

func (MkVarUseModifier) IsToLower

func (m MkVarUseModifier) IsToLower() bool

func (MkVarUseModifier) MatchMatch

func (m MkVarUseModifier) MatchMatch() (ok bool, positive bool, pattern string, exact bool)

MatchMatch tries to match the modifier to a :M or a :N pattern matching. Examples:

:Mpattern   => true,  true,  "pattern", true
:M*         => true,  true,  "*",       false
:M${VAR}    => true,  true,  "${VAR}",  false
:Npattern   => true,  false, "pattern", true
:X          => false

func (MkVarUseModifier) MatchSubst

func (m MkVarUseModifier) MatchSubst() (ok bool, regex bool, from string, to string, options string)

func (MkVarUseModifier) Quoted

func (m MkVarUseModifier) Quoted() string

func (MkVarUseModifier) String

func (m MkVarUseModifier) String() string

func (MkVarUseModifier) Subst

func (m MkVarUseModifier) Subst(str string) (bool, string)

Subst evaluates an S/from/to/ modifier.

Example:

MkVarUseModifier{"S,name,file,g"}.Subst("distname-1.0") => "distfile-1.0"

type Once

type Once struct {

	// Only used during testing, to trace the actual arguments,
	// since hashing is a one-way function.
	Trace bool
	// contains filtered or unexported fields
}

Once remembers with which arguments its FirstTime method has been called and only returns true on each first call.

func (*Once) FirstTime

func (o *Once) FirstTime(what string) bool

func (*Once) FirstTimeSlice

func (o *Once) FirstTimeSlice(whats ...string) bool

func (*Once) Seen

func (o *Once) Seen(what string) bool

func (*Once) SeenSlice

func (o *Once) SeenSlice(whats ...string) bool

type OptionsLinesChecker

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

OptionsLinesChecker checks an options.mk file of a pkgsrc package.

See mk/bsd.options.mk for a detailed description.

func (*OptionsLinesChecker) Check

func (ck *OptionsLinesChecker) Check()

type Package

type Package struct {
	Pkgpath PkgsrcPath // e.g. "category/pkgdir"

	EffectivePkgname     string  // PKGNAME or DISTNAME from the package Makefile, including nb13, can be empty
	EffectivePkgbase     string  // EffectivePkgname without the version
	EffectivePkgversion  string  // The version part of the effective PKGNAME, excluding nb13
	EffectivePkgnameLine *MkLine // The origin of the three Effective* values

	Pkgdir       PackagePath  // PKGDIR from the package Makefile
	Filesdir     PackagePath  // FILESDIR from the package Makefile
	Patchdir     PackagePath  // PATCHDIR from the package Makefile
	DistinfoFile PackagePath  // DISTINFO_FILE from the package Makefile
	Plist        PlistContent // Files and directories mentioned in the PLIST files
	PlistLines   *PlistLines

	IgnoreMissingPatches bool // In distinfo, don't warn about patches that cannot be found.

	Once Once
	// contains filtered or unexported fields
}

Package is the pkgsrc package that is currently checked.

Most of the information is loaded first, and after loading the actual checks take place. This is necessary because variables in Makefiles may be used before they are defined, and such dependencies often span multiple files that are included indirectly.

func NewPackage

func NewPackage(dir CurrPath) *Package

func (*Package) AutofixDistinfo

func (pkg *Package) AutofixDistinfo(oldSha1, newSha1 string)

func (*Package) Check

func (pkg *Package) Check()

func (*Package) CheckVarorder

func (pkg *Package) CheckVarorder(mklines *MkLines)

CheckVarorder checks that in simple package Makefiles, the most common variables appear in a fixed order. The order itself is a little arbitrary but provides at least a bit of consistency.

func (*Package) File

func (pkg *Package) File(relativeFileName PackagePath) CurrPath

File returns the (possibly absolute) path to relativeFileName, as resolved from the package's directory. Variables that are known in the package are resolved, e.g. ${PKGDIR}.

func (*Package) Includes

func (pkg *Package) Includes(filename PackagePath) *MkLine

Returns whether the given file (relative to the package directory) is included somewhere in the package, either directly or indirectly.

func (*Package) Rel

func (pkg *Package) Rel(filename CurrPath) PackagePath

Rel returns the path by which the given filename (as seen from the current working directory) can be reached as a relative path from the package directory.

Example:

NewPackage("category/package").Rel("other/package") == "../../other/package"

type PackagePath

type PackagePath string

PackagePath is a path relative to the package directory. It is used for the PATCHDIR and PKGDIR variables, as well as dependencies and conflicts on other packages.

It can have two forms:

  • patches (further down)
  • ../../category/package/* (up to the pkgsrc root, then down again)

func NewPackagePath

func NewPackagePath(p RelPath) PackagePath

func NewPackagePathString

func NewPackagePathString(p string) PackagePath

func (PackagePath) AsPath

func (p PackagePath) AsPath() Path

func (PackagePath) AsRelPath

func (p PackagePath) AsRelPath() RelPath

func (PackagePath) CleanPath

func (p PackagePath) CleanPath() PackagePath

func (PackagePath) ContainsPath

func (p PackagePath) ContainsPath(sub Path) bool

func (PackagePath) ContainsText

func (p PackagePath) ContainsText(contained string) bool

func (PackagePath) HasPrefixPath

func (p PackagePath) HasPrefixPath(sub Path) bool

func (PackagePath) IsEmpty

func (p PackagePath) IsEmpty() bool

func (PackagePath) JoinNoClean

func (p PackagePath) JoinNoClean(other RelPath) PackagePath

func (PackagePath) Replace

func (p PackagePath) Replace(from, to string) PackagePath

func (PackagePath) String

func (p PackagePath) String() string

type Paragraph

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

Paragraph is a slice of Makefile lines that is surrounded by empty lines.

All variable assignments in a paragraph should be aligned in the same column.

func NewParagraph

func NewParagraph(mklines *MkLines, from, to int) *Paragraph

func (*Paragraph) Align

func (p *Paragraph) Align()

func (*Paragraph) AlignTo

func (p *Paragraph) AlignTo(column int)

AlignTo realigns all variable assignments in the paragraph so that their values start in the same column. Variable assignments that are commented out are also realigned.

No warning or note is logged. Therefore this method must only be used to realign the whole paragraph after one of its lines has been modified.

func (*Paragraph) FirstLine

func (p *Paragraph) FirstLine() *MkLine

func (*Paragraph) ForEach

func (p *Paragraph) ForEach(action func(mkline *MkLine))

func (*Paragraph) LastLine

func (p *Paragraph) LastLine() *MkLine

func (*Paragraph) MkLines

func (p *Paragraph) MkLines() []*MkLine

type ParseError

type ParseError struct {
	RemainingTokens []string
}

func (*ParseError) Error

func (e *ParseError) Error() string

type PatchChecker

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

func (*PatchChecker) Check

func (ck *PatchChecker) Check(pkg *Package)

type Path

type Path string

Path is a slash-separated path. It may or may not resolve to an existing file. It may be absolute or relative. Some paths may contain placeholders like @VAR@ or ${VAR}. The base directory of relative paths is unspecified.

func NewPath

func NewPath(p string) Path

func (Path) Base

func (p Path) Base() RelPath

func (Path) Clean

func (p Path) Clean() Path

func (Path) CleanDot

func (p Path) CleanDot() Path

CleanDot returns the path with single dots removed and double slashes collapsed.

func (Path) CleanPath

func (p Path) CleanPath() Path

CleanPath is similar to path.Clean. The difference is that only "../../" is replaced, not "../". Also, the initial directory is always kept. This is to provide the package path as context in deeply nested .include chains.

func (Path) ContainsPath

func (p Path) ContainsPath(sub Path) bool

ContainsPath returns whether the sub path is part of the path. The basic unit of comparison is a path component, not a character.

Note that the paths used in pkglint may contain seemingly unnecessary components, like "../../wip/mk/../../devel/gettext-lib". To ignore these components, use ContainsPathCanonical instead.

func (Path) ContainsText

func (p Path) ContainsText(contained string) bool

func (Path) Count

func (p Path) Count() int

Count returns the number of meaningful parts of the path. See Parts.

func (Path) Dir

func (p Path) Dir() Path

Dir returns the directory of the path, with only minimal cleaning. Only redundant dots and slashes are removed, and only at the end.

func (Path) GoString

func (p Path) GoString() string

func (Path) HasBase

func (p Path) HasBase(base string) bool

func (Path) HasPrefixPath

func (p Path) HasPrefixPath(prefix Path) bool

HasPrefixPath returns whether the path starts with the given prefix. The basic unit of comparison is a path component, not a character.

func (Path) HasPrefixText

func (p Path) HasPrefixText(prefix string) bool

func (Path) HasSuffixPath

func (p Path) HasSuffixPath(suffix Path) bool

HasSuffixPath returns whether the path ends with the given suffix. The basic unit of comparison is a path component, not a character.

func (Path) HasSuffixText

func (p Path) HasSuffixText(suffix string) bool

func (Path) IsAbs

func (p Path) IsAbs() bool

func (Path) IsEmpty

func (p Path) IsEmpty() bool

IsEmpty returns true if the path is completely empty, which is usually a sign of an uninitialized variable.

func (Path) JoinClean

func (p Path) JoinClean(s RelPath) Path

func (Path) JoinNoClean

func (p Path) JoinNoClean(s RelPath) Path

func (Path) Parts

func (p Path) Parts() []string

Parts splits the path into its components. Multiple adjacent slashes are treated like a single slash. Parts that are single dots are skipped. Absolute paths have an empty string as its first part. All other parts are nonempty.

func (Path) Rel

func (p Path) Rel(other Path) RelPath

Rel returns the relative path from this path to the other.

The returned path is a canonical relative path. It starts with a possibly empty sequence of "../", followed by a possibly empty sequence of non-dotdot directories. It may have a single dot at the end, which means the path goes to a directory.

func (Path) Replace

func (p Path) Replace(from, to string) Path

func (Path) Split

func (p Path) Split() (dir Path, base string)

func (Path) String

func (p Path) String() string

func (Path) TrimSuffix

func (p Path) TrimSuffix(suffix string) Path

type Pkglint

type Pkglint struct {
	CheckGlobal bool

	WarnExtra,
	WarnPerm,
	WarnQuoting bool

	Profiling,
	DumpMakefile,
	Import,
	Network,
	Recursive bool

	Pkgsrc Pkgsrc // Global data, mostly extracted from mk/*.

	Todo CurrPathQueue // The files or directories that still need to be checked.

	Wip            bool   // Is the currently checked file or package from pkgsrc-wip?
	Infrastructure bool   // Is the currently checked file from the pkgsrc infrastructure?
	Testing        bool   // Is pkglint in self-testing mode (only during development)?
	Experimental   bool   // For experimental features, only enabled individually in tests
	Username       string // For checking against OWNER and MAINTAINER

	Logger Logger

	InterPackage InterPackage
	// contains filtered or unexported fields
}

Pkglint is a container for all global variables of this Go package.

func NewPkglint

func NewPkglint(stdout io.Writer, stderr io.Writer) Pkglint

func (*Pkglint) Abs

func (p *Pkglint) Abs(filename CurrPath) CurrPath

func (*Pkglint) Check

func (p *Pkglint) Check(dirent CurrPath)

Check checks a directory entry, which can be a regular file, a directory or a symlink (only allowed for the working directory).

This is the method that is called for each command line argument.

It sets up all the global state (infrastructure, wip) for accurately classifying the entry.

func (*Pkglint) Main

func (p *Pkglint) Main(stdout io.Writer, stderr io.Writer, args []string) (exitCode int)

Main runs the main program with the given arguments. args[0] is the program name.

Note: during tests, calling this method disables tracing because the getopt parser resets all options before the actual parsing. One of these options is trace.Tracing, which is connected to --debug.

It also discards the -Wall option that is used by default in other tests.

func (*Pkglint) ParseCommandLine

func (p *Pkglint) ParseCommandLine(args []string) int

func (*Pkglint) Tool

func (p *Pkglint) Tool(mklines *MkLines, command string, time ToolTime) (tool *Tool, usable bool)

Tool returns the tool definition from the closest scope (file, global), or nil. The command can be "sed" or "gsed" or "${SED}". If a tool is returned, usable tells whether that tool has been added to USE_TOOLS in the current scope (file or package).

func (*Pkglint) ToolByVarname

func (p *Pkglint) ToolByVarname(mklines *MkLines, varname string) *Tool

ToolByVarname looks up the tool by its variable name, e.g. "SED".

The returned tool may come either from the current file or the current package. It is not guaranteed to be usable (added to USE_TOOLS), only defined; that must be checked by the calling code, see Tool.UsableAtLoadTime and Tool.UsableAtRunTime.

type Pkgsrc

type Pkgsrc struct {
	Tools *Tools

	MasterSiteURLToVar map[string]string // "github.com/" => "MASTER_SITE_GITHUB"
	MasterSiteVarToURL map[string]string // "MASTER_SITE_GITHUB" => "https://github.com/"

	PkgOptions map[string]string // "x11" => "Provides X11 support"

	LastChange      map[PkgsrcPath]*Change
	LastFreezeStart string // e.g. "2018-01-01", or ""
	LastFreezeEnd   string // e.g. "2018-01-01", or ""

	// Variables that may be overridden by the pkgsrc user.
	// They are typically defined in mk/defaults/mk.conf.
	//
	// Whenever a package uses such a variable, it must add the variable name
	// to BUILD_DEFS.
	UserDefinedVars Scope

	Deprecated map[string]string
	// contains filtered or unexported fields
}

Pkgsrc describes a pkgsrc installation. In each pkglint run, only a single pkgsrc installation is ever loaded. It just doesn't make sense to check multiple pkgsrc installations at once.

This type only contains data that is loaded once and then stays constant. Everything else (distfile hashes, package names) is recorded in the InterPackage type instead.

func NewPkgsrc

func NewPkgsrc(dir CurrPath) Pkgsrc

func (*Pkgsrc) File

func (src *Pkgsrc) File(relativeName PkgsrcPath) CurrPath

File resolves a filename relative to the pkgsrc top directory.

Example:

NewPkgsrc("/usr/pkgsrc").File("distfiles") => "/usr/pkgsrc/distfiles"

func (*Pkgsrc) FilePkg

func (src *Pkgsrc) FilePkg(rel PackagePath) CurrPath

FilePkg resolves a package-relative path to the real file that it represents. If the given path does not start with "../../", the result is empty.

func (*Pkgsrc) IsBuildDef

func (src *Pkgsrc) IsBuildDef(varname string) bool

IsBuildDef returns whether the given variable is automatically added to BUILD_DEFS by the pkgsrc infrastructure. In such a case, the package doesn't need to add the variable to BUILD_DEFS itself.

func (*Pkgsrc) IsInfra

func (src *Pkgsrc) IsInfra(filename CurrPath) bool

IsInfra returns whether the given filename is part of the pkgsrc infrastructure.

func (*Pkgsrc) IsInfraMain

func (src *Pkgsrc) IsInfraMain(filename CurrPath) bool

func (*Pkgsrc) IsWip

func (src *Pkgsrc) IsWip(filename CurrPath) bool

func (*Pkgsrc) Latest

func (src *Pkgsrc) Latest(category PkgsrcPath, re regex.Pattern, repl string) string

Latest returns the latest package matching the given pattern. It searches the category for subdirectories matching the given regular expression, takes the latest of them and replaces its name with repl.

Example:

Latest("lang", `^php[0-9]+$`, "../../lang/$0")
    => "../../lang/php72"

func (*Pkgsrc) ListVersions

func (src *Pkgsrc) ListVersions(category PkgsrcPath, re regex.Pattern, repl string, errorIfEmpty bool) []string

ListVersions searches the category for subdirectories matching the given regular expression, replaces their names with repl and returns a slice of them, properly sorted from early to late.

Example:

ListVersions("lang", `^php[0-9]+$`, "php-$0")
    => {"php-53", "php-56", "php-73"}

func (*Pkgsrc) Load

func (src *Pkgsrc) Load(filename PkgsrcPath, options LoadOptions) *Lines

Load loads the file relative to the pkgsrc top directory.

func (*Pkgsrc) LoadInfrastructure

func (src *Pkgsrc) LoadInfrastructure()

LoadInfrastructure reads the pkgsrc infrastructure files to extract information like the tools, packages to update, user-defined variables.

This work is not done in the constructor to keep the tests simple, since setting up a realistic pkgsrc environment requires a lot of files.

func (*Pkgsrc) LoadMk

func (src *Pkgsrc) LoadMk(filename PkgsrcPath, options LoadOptions) *MkLines

LoadMk loads the Makefile relative to the pkgsrc top directory.

func (*Pkgsrc) LoadMkExisting

func (src *Pkgsrc) LoadMkExisting(filename PkgsrcPath) *MkLines

LoadMkExisting loads a file that must exist.

During pkglint testing, these files often don't exist, as they are emulated by setting their data structures manually. In that case, returns nil.

func (*Pkgsrc) ReadDir

func (src *Pkgsrc) ReadDir(dirName PkgsrcPath) []os.FileInfo

ReadDir lists the files and subdirectories from the given directory (relative to the pkgsrc root).

The result may contain empty directories that are left over from CVS. For performance reasons, the caller needs to filter these out; see isEmptyDir.

func (*Pkgsrc) Rel

func (src *Pkgsrc) Rel(filename CurrPath) PkgsrcPath

Rel returns the path of `filename`, relative to the pkgsrc top directory.

Example:

NewPkgsrc("/usr/pkgsrc").Rel("/usr/pkgsrc/distfiles") => "distfiles"

func (*Pkgsrc) Relpath

func (src *Pkgsrc) Relpath(from, to CurrPath) RelPath

Relpath returns the canonical relative path from the directory "from" to the filesystem entry "to".

The relative path is built by going from the "from" directory up to the pkgsrc root and from there to the "to" filename. This produces the form "../../category/package" that is found in DEPENDS and .include lines.

This function should only be used if the relative path from one file to another cannot be computed in another way. The preferred way is to take the relative filenames directly from the .include or exists() where they appear.

func (*Pkgsrc) SuggestedUpdates

func (src *Pkgsrc) SuggestedUpdates() []SuggestedUpdate

func (*Pkgsrc) VariableType

func (src *Pkgsrc) VariableType(mklines *MkLines, varname string) (vartype *Vartype)

VariableType returns the type of the variable (possibly guessed based on the variable name), or nil if the type cannot even be guessed.

type PkgsrcPath

type PkgsrcPath string

PkgsrcPath is a path relative to the pkgsrc root.

func NewPkgsrcPath

func NewPkgsrcPath(p Path) PkgsrcPath

func (PkgsrcPath) AsPath

func (p PkgsrcPath) AsPath() Path

func (PkgsrcPath) AsRelPath

func (p PkgsrcPath) AsRelPath() RelPath

func (PkgsrcPath) Base

func (p PkgsrcPath) Base() RelPath

func (PkgsrcPath) Count

func (p PkgsrcPath) Count() int

func (PkgsrcPath) Dir

func (p PkgsrcPath) Dir() PkgsrcPath

func (PkgsrcPath) HasPrefixPath

func (p PkgsrcPath) HasPrefixPath(prefix Path) bool

func (PkgsrcPath) JoinNoClean

func (p PkgsrcPath) JoinNoClean(other RelPath) PkgsrcPath

func (PkgsrcPath) String

func (p PkgsrcPath) String() string

type PlistChecker

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

func NewPlistChecker

func NewPlistChecker(pkg *Package) *PlistChecker

func (*PlistChecker) Check

func (ck *PlistChecker) Check(plainLines *Lines)

func (*PlistChecker) Load

func (ck *PlistChecker) Load(lines *Lines) []*PlistLine

type PlistContent

type PlistContent struct {
	Dirs       map[RelPath]*PlistLine
	Files      map[RelPath]*PlistLine
	Conditions map[string]bool // each ${PLIST.id} sets ["id"] = true.
}

PlistContent lists the directories and files that appear in the package's PLIST files. It serves two purposes:

1. Decide whether AUTO_MKDIRS can be used instead of listing the INSTALLATION_DIRS redundantly.

2. Ensure that the entries mentioned in the ALTERNATIVES file also appear in the PLIST files.

func NewPlistContent

func NewPlistContent() PlistContent

type PlistLine

type PlistLine struct {
	Line *Line
	// contains filtered or unexported fields
}

func (*PlistLine) Autofix

func (pline *PlistLine) Autofix() *Autofix

func (*PlistLine) CheckDirective

func (pline *PlistLine) CheckDirective(cmd, arg string)

func (*PlistLine) CheckTrailingWhitespace

func (pline *PlistLine) CheckTrailingWhitespace()

func (*PlistLine) Errorf

func (pline *PlistLine) Errorf(format string, args ...interface{})

func (*PlistLine) Explain

func (pline *PlistLine) Explain(explanation ...string)

func (*PlistLine) HasPath

func (pline *PlistLine) HasPath() bool

func (*PlistLine) HasPlainPath

func (pline *PlistLine) HasPlainPath() bool

func (*PlistLine) Path

func (pline *PlistLine) Path() RelPath

func (*PlistLine) RelLine

func (pline *PlistLine) RelLine(other *Line) string

func (*PlistLine) Warnf

func (pline *PlistLine) Warnf(format string, args ...interface{})

type PlistLines

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

func NewPlistLines

func NewPlistLines() *PlistLines

func (*PlistLines) Add

func (pl *PlistLines) Add(line *PlistLine, rank *PlistRank)

type PlistRank

type PlistRank struct {
	Rank  int
	Opsys string
	Arch  string
	Rest  string
}

func NewPlistRank

func NewPlistRank(basename RelPath) *PlistRank

func (*PlistRank) MoreGeneric

func (r *PlistRank) MoreGeneric(other *PlistRank) bool

The ranks among the files are:

PLIST
-> PLIST.common
-> PLIST.common_end
-> { PLIST.OPSYS, PLIST.ARCH }
-> { PLIST.OPSYS.ARCH, PLIST.EMUL_PLATFORM }

Files are a later level must not mention files that are already mentioned at an earlier level.

type RawLine

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

func (*RawLine) Orig

func (rline *RawLine) Orig() string

type RedundantScope

type RedundantScope struct {
	IsRelevant func(mkline *MkLine) bool
	// contains filtered or unexported fields
}

RedundantScope checks for redundant variable definitions and for variables that are accidentally overwritten. It tries to be as correct as possible by not flagging anything that is defined conditionally.

There may be some edge cases though like defining PKGNAME, then evaluating it using :=, then defining it again. This pattern is so error-prone that it should not appear in pkgsrc at all, thus pkglint doesn't even expect it. (Well, except for the PKGNAME case, but that's deep in the infrastructure and only affects the "nb13" extension.)

TODO: This scope is not only used for detecting redundancies. It also provides information about whether the variables are constant or depend on other variables. Therefore the name may change soon.

func NewRedundantScope

func NewRedundantScope() *RedundantScope

func (*RedundantScope) Check

func (s *RedundantScope) Check(mklines *MkLines)

type RelPath

type RelPath string

RelPath is a path that is relative to some base directory that is not further specified.

func MatchMkInclude

func MatchMkInclude(text string) (m bool, indentation, directive string, filename RelPath)

func NewRelPath

func NewRelPath(p Path) RelPath

func NewRelPathString

func NewRelPathString(p string) RelPath

func (RelPath) AsPath

func (p RelPath) AsPath() Path

func (RelPath) Base

func (p RelPath) Base() RelPath

func (RelPath) Clean

func (p RelPath) Clean() RelPath

func (RelPath) CleanDot

func (p RelPath) CleanDot() RelPath

func (RelPath) CleanPath

func (p RelPath) CleanPath() RelPath

func (RelPath) ContainsPath

func (p RelPath) ContainsPath(sub Path) bool

func (RelPath) ContainsText

func (p RelPath) ContainsText(text string) bool

func (RelPath) Count

func (p RelPath) Count() int

func (RelPath) Dir

func (p RelPath) Dir() RelPath

func (RelPath) HasBase

func (p RelPath) HasBase(base string) bool

func (RelPath) HasPrefixPath

func (p RelPath) HasPrefixPath(prefix Path) bool

func (RelPath) HasPrefixText

func (p RelPath) HasPrefixText(prefix string) bool

func (RelPath) HasSuffixPath

func (p RelPath) HasSuffixPath(suffix Path) bool

func (RelPath) HasSuffixText

func (p RelPath) HasSuffixText(suffix string) bool

func (RelPath) IsEmpty

func (p RelPath) IsEmpty() bool

func (RelPath) JoinNoClean

func (p RelPath) JoinNoClean(other RelPath) RelPath

func (RelPath) Parts

func (p RelPath) Parts() []string

func (RelPath) Rel

func (p RelPath) Rel(other Path) RelPath

func (RelPath) Replace

func (p RelPath) Replace(from string, to string) RelPath

func (RelPath) Split

func (p RelPath) Split() (RelPath, string)

func (RelPath) String

func (p RelPath) String() string

type Scope

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

Scope remembers which variables are defined and which are used in a certain scope, such as a package or a file.

TODO: Decide whether the scope should consider variable assignments

from the pkgsrc infrastructure. For Package.checkGnuConfigureUseLanguages
it would be better to ignore them completely.

TODO: Merge this code with Var, which defines essentially the

same features.

See also substScope, which already analyzes the possible variable values based on the conditional code paths.

See also RedundantScope.

func NewScope

func NewScope() Scope

func (*Scope) Commented

func (s *Scope) Commented(varname string) *MkLine

Commented returns whether the variable has only been defined in commented variable assignments. These are ignored by bmake but used heavily in mk/defaults/mk.conf for documentation.

func (*Scope) Define

func (s *Scope) Define(varname string, mkline *MkLine)

Define marks the variable and its canonicalized form as defined.

func (*Scope) DefineAll

func (s *Scope) DefineAll(other *Scope)

func (*Scope) Fallback

func (s *Scope) Fallback(varname string, value string)

func (*Scope) FirstDefinition

func (s *Scope) FirstDefinition(varname string) *MkLine

FirstDefinition returns the line in which the variable has been defined first.

Having multiple definitions is typical in the branches of "if" statements.

Another typical case involves two files: the included file defines a default value, and the including file later overrides that value. Or the other way round: the including file sets a value first, and the included file then assigns a default value using ?=.

func (*Scope) FirstUse

func (s *Scope) FirstUse(varname string) *MkLine

func (*Scope) IsDefined

func (s *Scope) IsDefined(varname string) bool

IsDefined tests whether the variable is defined. It does NOT test the canonicalized variable name.

Even if IsDefined returns true, FirstDefinition doesn't necessarily return true since the latter ignores the default definitions from vardefs.go, keyword dummyVardefMkline.

func (*Scope) IsDefinedSimilar

func (s *Scope) IsDefinedSimilar(varname string) bool

IsDefinedSimilar tests whether the variable or its canonicalized form is defined.

func (*Scope) IsUsed

func (s *Scope) IsUsed(varname string) bool

IsUsed tests whether the variable is used. It does NOT test the canonicalized variable name.

func (*Scope) IsUsedAtLoadTime

func (s *Scope) IsUsedAtLoadTime(varname string) bool

IsUsedAtLoadTime returns true if the variable is used at load time somewhere.

func (*Scope) IsUsedSimilar

func (s *Scope) IsUsedSimilar(varname string) bool

IsUsedSimilar tests whether the variable or its canonicalized form is used.

func (*Scope) LastDefinition

func (s *Scope) LastDefinition(varname string) *MkLine

LastDefinition returns the line in which the variable has been defined last.

Having multiple definitions is typical in the branches of "if" statements.

Another typical case involves two files: the included file defines a default value, and the including file later overrides that value. Or the other way round: the including file sets a value first, and the included file then assigns a default value using ?=.

func (*Scope) LastValue

func (s *Scope) LastValue(varname string) string

LastValue returns the value from the last variable definition.

If an empty string is returned, this can mean either that the variable value is indeed the empty string or that the variable was not found, or that the variable value cannot be determined reliably. To distinguish these cases, call LastValueFound instead.

func (*Scope) LastValueFound

func (s *Scope) LastValueFound(varname string) (value string, found bool, indeterminate bool)

func (*Scope) Mentioned

func (s *Scope) Mentioned(varname string) *MkLine

Mentioned returns the first line in which the variable is either:

  • defined,
  • mentioned in a commented variable assignment,
  • mentioned in a documentation comment.

func (*Scope) Use

func (s *Scope) Use(varname string, mkline *MkLine, time VucTime)

Use marks the variable and its canonicalized form as used.

type SeparatorWriter

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

SeparatorWriter writes output, occasionally separated by an empty line. This is used for separating the diagnostics when --source is combined with --show-autofix, where each log message consists of multiple lines.

func NewSeparatorWriter

func NewSeparatorWriter(out io.Writer) *SeparatorWriter

func (*SeparatorWriter) Flush

func (wr *SeparatorWriter) Flush()

func (*SeparatorWriter) Separate

func (wr *SeparatorWriter) Separate()

Separate remembers to output an empty line before the next character.

The writer must not be in the middle of a line.

func (*SeparatorWriter) Write

func (wr *SeparatorWriter) Write(text string)

func (*SeparatorWriter) WriteLine

func (wr *SeparatorWriter) WriteLine(text string)

type ShAtom

type ShAtom struct {
	Type    ShAtomType
	MkText  string
	Quoting ShQuoting // The quoting state at the end of the token
	// contains filtered or unexported fields
}

func (*ShAtom) ShVarname

func (atom *ShAtom) ShVarname() string

ShVarname applies to shell variable atoms like $$varname or $${varname:-modifier} and returns the name of the shell variable.

func (*ShAtom) String

func (atom *ShAtom) String() string

func (*ShAtom) VarUse

func (atom *ShAtom) VarUse() *MkVarUse

VarUse returns a read access to a Makefile variable, or nil for plain shell tokens.

type ShAtomType

type ShAtomType uint8

func (ShAtomType) IsWord

func (t ShAtomType) IsWord() bool

IsWord checks whether the atom counts as text. Makefile variables, shell variables and other text counts, but keywords, operators and separators don't.

func (ShAtomType) String

func (t ShAtomType) String() string

type ShQuoting

type ShQuoting uint8

ShQuoting describes the context in which a string appears and how it must be unescaped to get its literal value.

func (ShQuoting) String

func (q ShQuoting) String() string

String returns a very short identifier for the quoting state. In this, d means double quotes, s means single quotes, b means backticks and S means subshell.

func (ShQuoting) ToVarUseContext

func (q ShQuoting) ToVarUseContext() VucQuoting

type ShToken

type ShToken struct {
	MkText string // The text as it appeared in the Makefile, after replacing `\#` with `#`
	Atoms  []*ShAtom
}

ShToken is an operator or a keyword or some text intermingled with variables.

Examples:

;
then
"The number of pkgsrc packages in ${PREFIX} is $$packages."

See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10_02

func NewShToken

func NewShToken(mkText string, atoms ...*ShAtom) *ShToken

func (*ShToken) String

func (token *ShToken) String() string

type ShTokenizer

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

func NewShTokenizer

func NewShTokenizer(diag Autofixer, text string) *ShTokenizer

func (*ShTokenizer) Rest

func (p *ShTokenizer) Rest() string

func (*ShTokenizer) ShAtom

func (p *ShTokenizer) ShAtom(quoting ShQuoting) *ShAtom

ShAtom parses a basic building block of a shell program. Examples for such atoms are: variable reference (both make and shell), operator, text, quote, space.

See ShQuote.Feed

func (*ShTokenizer) ShAtoms

func (p *ShTokenizer) ShAtoms() []*ShAtom

func (*ShTokenizer) ShToken

func (p *ShTokenizer) ShToken() *ShToken

type ShellLexer

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

ShellLexer categorizes tokens for shell commands, providing the lexer required by the yacc-generated parser.

The main work of tokenizing is done in ShellTokenizer though.

Example:

while :; do var=$$other; done

=>

while
space " "
word ":"
semicolon
space " "
do
space " "
assign "var=$$other"
semicolon
space " "
done

See splitIntoShellTokens and ShellTokenizer.

func NewShellLexer

func NewShellLexer(tokens []string, rest string) *ShellLexer

func (*ShellLexer) Error

func (lex *ShellLexer) Error(s string)

func (*ShellLexer) Lex

func (lex *ShellLexer) Lex(lval *shyySymType) (ttype int)

type ShellLineChecker

type ShellLineChecker struct {
	MkLines *MkLines
	// contains filtered or unexported fields
}

ShellLineChecker checks either a line from a Makefile starting with a tab, thereby containing shell commands to be executed.

Or it checks a variable assignment line from a Makefile with a left-hand side variable that is of some shell-like type; see Vartype.IsShell.

func NewShellLineChecker

func NewShellLineChecker(mklines *MkLines, mkline *MkLine) *ShellLineChecker

func (*ShellLineChecker) CheckShellCommand

func (ck *ShellLineChecker) CheckShellCommand(shellcmd string, pSetE *bool, time ToolTime)

func (*ShellLineChecker) CheckShellCommandLine

func (ck *ShellLineChecker) CheckShellCommandLine(shelltext string)

func (*ShellLineChecker) CheckShellCommands

func (ck *ShellLineChecker) CheckShellCommands(shellcmds string, time ToolTime)

CheckShellCommands checks for a list of shell commands, of which each one is terminated with a semicolon. These are used in GENERATE_PLIST.

func (*ShellLineChecker) CheckWord

func (ck *ShellLineChecker) CheckWord(token string, checkQuoting bool, time ToolTime)

func (*ShellLineChecker) Explain

func (ck *ShellLineChecker) Explain(explanation ...string)

func (*ShellLineChecker) Warnf

func (ck *ShellLineChecker) Warnf(format string, args ...interface{})

type SimpleCommandChecker

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

func NewSimpleCommandChecker

func NewSimpleCommandChecker(cmd *MkShSimpleCommand, time ToolTime, mkline *MkLine, mklines *MkLines) *SimpleCommandChecker

func (*SimpleCommandChecker) Check

func (scc *SimpleCommandChecker) Check()

func (*SimpleCommandChecker) Errorf

func (scc *SimpleCommandChecker) Errorf(format string, args ...interface{})

func (*SimpleCommandChecker) Explain

func (scc *SimpleCommandChecker) Explain(explanation ...string)

func (*SimpleCommandChecker) Notef

func (scc *SimpleCommandChecker) Notef(format string, args ...interface{})

func (*SimpleCommandChecker) Warnf

func (scc *SimpleCommandChecker) Warnf(format string, args ...interface{})

type StrCommand

type StrCommand struct {
	Assignments []string
	Name        string
	Args        []string
}

StrCommand is structurally similar to MkShSimpleCommand, but all components are converted to strings to allow for simpler checks, especially for analyzing command line options.

Example:

LC_ALL=C sort */*.c > sorted

func NewStrCommand

func NewStrCommand(cmd *MkShSimpleCommand) *StrCommand

func (*StrCommand) AnyArgMatches

func (c *StrCommand) AnyArgMatches(pattern regex.Pattern) bool

func (*StrCommand) HasOption

func (c *StrCommand) HasOption(opt string) bool

HasOption checks whether one of the arguments is exactly the given opt.

func (*StrCommand) String

func (c *StrCommand) String() string

type StringInterner

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

StringInterner collects commonly used strings to avoid wasting heap memory by duplicated strings.

func NewStringInterner

func NewStringInterner() StringInterner

func (*StringInterner) Intern

func (si *StringInterner) Intern(str string) string

type StringSet

type StringSet struct {
	Elements []string
	// contains filtered or unexported fields
}

StringSet stores unique strings in insertion order.

func NewStringSet

func NewStringSet() StringSet

func (*StringSet) Add

func (s *StringSet) Add(element string)

func (*StringSet) AddAll

func (s *StringSet) AddAll(elements []string)

type SubstContext

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

SubstContext records the state of a block of variable assignments that make up a SUBST class.

See mk/subst.mk.

func NewSubstContext

func NewSubstContext(pkg *Package) *SubstContext

func (*SubstContext) Finish

func (ctx *SubstContext) Finish(diag Diagnoser)

func (*SubstContext) Process

func (ctx *SubstContext) Process(mkline *MkLine)

type SuggestedUpdate

type SuggestedUpdate struct {
	Line    Location
	Pkgname string
	Version string
	Comment string
}

SuggestedUpdate describes a desired package update, from the doc/TODO file.

type Tool

type Tool struct {
	Name    string // e.g. "sed", "gzip"
	Varname string // e.g. "SED", "GZIP_CMD"

	// Some of the very simple tools (echo, printf, test) differ in their implementations.
	//
	// When bmake encounters a "simple" command line, it bypasses the
	// call to a shell (see devel/bmake/files/compat.c:/useShell/).
	// Therefore, sometimes the shell builtin is run, and sometimes the
	// native tool.
	//
	// In particular, this decision depends on PKG_DEBUG_LEVEL
	// since that variable adds a semicolon to the command line, which is
	// considered one of the characters that force the commands being
	// executed by the shell. As of December 2018, the list of special characters
	// is "~#=|^(){};&<>*?[]:$`\\\n".
	//
	// To work around this tricky situation, pkglint warns when these shell builtins
	// are used by their simple names (echo, test) instead of the variable form
	// (${ECHO}, ${TEST}).
	MustUseVarForm bool
	Validity       Validity
	Aliases        []string
	// contains filtered or unexported fields
}

Tool is one of the many standard shell utilities that are typically provided by the operating system, or, if missing, are installed via pkgsrc.

See `mk/tools/`.

func (*Tool) String

func (tool *Tool) String() string

func (*Tool) UsableAtLoadTime

func (tool *Tool) UsableAtLoadTime(seenPrefs bool) bool

UsableAtLoadTime means that the tool may be used by its variable name after bsd.prefs.mk has been included.

Additionally, all allowed cases from UsableAtRunTime are allowed.

VAR:=   ${TOOL}           # Not allowed since bsd.prefs.mk is not
                          # included yet.

.include "../../bsd.prefs.mk"

VAR:=   ${TOOL}           # Allowed.
VAR!=   ${TOOL}           # Allowed.

VAR=    ${${TOOL}:sh}     # Allowed; the :sh modifier is evaluated
                          # lazily, but when VAR should ever be
                          # evaluated at load time, this still means
                          # load time.

.if ${TOOL:T} == "tool"   # Allowed.
.endif

func (*Tool) UsableAtRunTime

func (tool *Tool) UsableAtRunTime() bool

UsableAtRunTime means that the tool may be used by its simple name in all {pre,do,post}-* targets, and by its variable name in all runtime contexts.

VAR:=   ${TOOL}           # Not allowed; TOOL might not be initialized yet.
VAR!=   ${TOOL}           # Not allowed; TOOL might not be initialized yet.

VAR=    ${${TOOL}:sh}     # Probably ok; the :sh modifier is evaluated at
                          # run time. But if VAR should ever be evaluated
                          # at load time (see the "Not allowed" cases
                          # above), it doesn't work. As of January 2019,
                          # pkglint cannot reliably distinguish these cases.

own-target:
        ${TOOL}           # Allowed.
        tool              # Not allowed because the PATH might not be set
                          # up for this target.

pre-configure:
        ${TOOL}           # Allowed.
        tool              # Allowed.

type ToolTime

type ToolTime uint8
const (
	LoadTime ToolTime = iota
	RunTime
)

func (ToolTime) String

func (t ToolTime) String() string

type Tools

type Tools struct {

	// Determines the effect of adding the tool to USE_TOOLS.
	//
	// As long as bsd.prefs.mk has definitely not been included by the current file,
	// tools added to USE_TOOLS are available at load time, but only after bsd.prefs.mk
	// has been included.
	//
	// Adding a tool to USE_TOOLS _after_ bsd.prefs.mk has been included, on the other
	// hand, only makes the tool available at run time.
	SeenPrefs bool

	// For example, "sed" is an alias of "gsed".
	//
	// This means when gsed is added to USE_TOOLS, sed is implicitly added as well.
	AliasOf map[string]string
	// contains filtered or unexported fields
}

Tools collects all tools for a certain scope (global or file) and remembers whether these tools are defined at all, and whether they are declared to be used via USE_TOOLS.

func NewTools

func NewTools() *Tools

func (*Tools) ByName

func (tr *Tools) ByName(name string) *Tool

func (*Tools) ByVarname

func (tr *Tools) ByVarname(varname string) *Tool

func (*Tools) Define

func (tr *Tools) Define(name, varname string, mkline *MkLine) *Tool

Define registers the tool by its name and the corresponding variable name (if nonempty). Depending on the given mkline, it may be added to USE_TOOLS automatically.

After this tool is added to USE_TOOLS, it may be used by this name (e.g. "awk") or by its variable (e.g. ${AWK}).

func (*Tools) ExistsVar

func (tr *Tools) ExistsVar(varname string) bool

func (*Tools) Fallback

func (tr *Tools) Fallback(other *Tools)

func (*Tools) IsValidToolName

func (tr *Tools) IsValidToolName(name string) bool

func (*Tools) ParseToolLine

func (tr *Tools) ParseToolLine(mklines *MkLines, mkline *MkLine, fromInfrastructure bool, addToUseTools bool)

ParseToolLine updates the tool definitions according to the given line from a Makefile.

If fromInfrastructure is true, the tool is defined even when it is only added to USE_TOOLS (which normally doesn't define anything). This way, pkglint also finds those tools whose definitions are too difficult to parse from the code.

If addToUseTools is true, a USE_TOOLS line makes a tool immediately usable. This should only be done if the current line is unconditional.

func (*Tools) Trace

func (tr *Tools) Trace()

func (*Tools) Usable

func (tr *Tools) Usable(tool *Tool, time ToolTime) bool

type Toplevel

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

type Validity

type Validity uint8
const (
	// Nowhere means that the tool has not been added
	// to USE_TOOLS and therefore cannot be used at all.
	Nowhere Validity = iota

	// AtRunTime means that the tool has been added to USE_TOOLS
	// after including bsd.prefs.mk and therefore cannot be used
	// at load time.
	//
	// The tool may be used as ${TOOL} in all targets.
	// The tool may be used by its plain name in {pre,do,post}-* targets.
	AtRunTime

	// AfterPrefsMk means that the tool has been added to USE_TOOLS
	// before including bsd.prefs.mk and therefore can be used at
	// load time after bsd.prefs.mk has been included.
	//
	// The tool may be used as ${TOOL} everywhere.
	// The tool may be used by its plain name in {pre,do,post}-* targets.
	AfterPrefsMk
)

func (Validity) String

func (time Validity) String() string

type Var

type Var struct {
	Name string
	// contains filtered or unexported fields
}

Var describes a variable in a Makefile snippet.

It keeps track of all places where the variable is accessed or modified (see ReadLocations, WriteLocations) and provides information for further static analysis, such as:

* Whether the variable value is constant, and if so, what the constant value is (see IsConstant, ConstantValue).

* What its (approximated) value is, either including values from the pkgsrc infrastructure (see ValueInfra) or excluding them (Value).

* On which other variables this variable depends (see IsConditional, ConditionalVars).

TODO: Decide how to handle OPSYS-specific variables, such as LDFLAGS.SunOS.

TODO: Decide how to handle parameterized variables, such as SUBST_MESSAGE.doc.

func NewVar

func NewVar(name string) *Var

func (*Var) AddRef

func (v *Var) AddRef(varname string)

AddRef marks this variable as being dependent on the given variable name. This can be used for the .for loops mentioned in Refs.

func (*Var) ConditionalVars

func (v *Var) ConditionalVars() []string

ConditionalVars returns all variables in conditions on which the value of this variable depends.

The returned slice must not be modified.

func (*Var) ConstantValue

func (v *Var) ConstantValue() string

ConstantValue returns the constant value of the variable. It is only allowed when IsConstant() returns true.

Variable assignments in the pkgsrc infrastructure are taken into account for determining the constant value.

func (*Var) IsConditional

func (v *Var) IsConditional() bool

IsConditional returns whether the variable value depends on other variables.

func (*Var) IsConstant

func (v *Var) IsConstant() bool

IsConstant returns whether the variable's value is a constant. It may reference other variables since these references are evaluated lazily, when the variable value is actually needed.

Multiple assignments (such as VAR=1, VAR+=2, VAR+=3) are considered to form a single constant as well, as long as the variable is not read before or in-between these assignments. The definition of "read" is very strict here since every mention of the variable counts. This may prevent some essentially constant values from being detected as such, but these special cases may be implemented later.

TODO: Simple .for loops that append to the variable are ok as well.

(This needs to be worded more precisely since that part potentially
adds a lot of complexity to the whole data structure.)

Variable assignments in the pkgsrc infrastructure are taken into account for determining whether a variable is constant.

func (*Var) Read

func (v *Var) Read(mkline *MkLine)

func (*Var) ReadLocations

func (v *Var) ReadLocations() []*MkLine

ReadLocations returns the locations where the variable is read, such as in ${VAR} or defined(VAR) or empty(VAR).

Uses inside conditionals are included, no matter whether they are actually reachable in practice.

Indirect uses through other variables (such as VAR2=${VAR}, VAR3=${VAR2}) are not listed.

Variable uses in the pkgsrc infrastructure are taken into account.

func (*Var) Refs

func (v *Var) Refs() []string

Refs returns all variables on which this variable depends. These are:

Variables that are referenced in the value, such as in VAR=${OTHER}.

Variables that are used in conditions that enclose one of the assignments to this variable, such as .if ${OPSYS} == NetBSD.

Variables that are used in .for loops in which this variable is assigned a value, such as DIRS in:

.for dir in ${DIRS}
VAR+=${dir}
.endfor

func (*Var) Value

func (v *Var) Value() string

Value returns the (approximated) value of the variable, taking into account all variable assignments that happen outside the pkgsrc infrastructure.

For variables that are conditionally assigned (as in .if/.else), the returned value is not reliable. It may be the value from either branch, or even the combined value of both branches.

See IsConstant and ConstantValue for more reliable information.

func (*Var) ValueInfra

func (v *Var) ValueInfra() string

ValueInfra returns the (approximated) value of the variable, taking into account all variable assignments from the package, the user and the pkgsrc infrastructure.

For variables that are conditionally assigned (as in .if/.else), the returned value is not reliable. It may be the value from either branch, or even the combined value of both branches.

See IsConstant and ConstantValue for more reliable information, but these ignore assignments from the infrastructure.

func (*Var) Write

func (v *Var) Write(mkline *MkLine, conditional bool, conditionVarnames ...string)

Write marks the variable as being assigned in the given line. Only standard assignments (VAR=value) are handled. Side-effect assignments (${VAR::=value}) are not handled here since they don't occur in practice.

func (*Var) WriteLocations

func (v *Var) WriteLocations() []*MkLine

WriteLocations returns the locations where the variable is modified.

Assignments inside conditionals are included, no matter whether they are actually reachable in practice.

Variable assignments in the pkgsrc infrastructure are taken into account.

type VarFact

type VarFact struct {
	MkLine  *MkLine
	Varname string
	Text    string
	Matches *makepat.Pattern
}

type VarTypeRegistry

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

func NewVarTypeRegistry

func NewVarTypeRegistry() VarTypeRegistry

func (*VarTypeRegistry) Canon

func (reg *VarTypeRegistry) Canon(varname string) *Vartype

func (*VarTypeRegistry) Define

func (reg *VarTypeRegistry) Define(varname string, basicType *BasicType, options vartypeOptions, aclEntries []ACLEntry)

func (*VarTypeRegistry) DefineName

func (reg *VarTypeRegistry) DefineName(varname string, basicType *BasicType, options vartypeOptions, aclName string)

DefineName registers a variable type given an ACL name. The available ACL names are listed in Init.

func (*VarTypeRegistry) DefineType

func (reg *VarTypeRegistry) DefineType(varcanon string, vartype *Vartype)

func (*VarTypeRegistry) Init

func (reg *VarTypeRegistry) Init(src *Pkgsrc)

Init initializes the long list of predefined pkgsrc variables. After this is done, PKGNAME, MAKE_ENV and all the other variables can be used in Makefiles without triggering warnings about typos.

func (*VarTypeRegistry) IsDefinedCanon

func (reg *VarTypeRegistry) IsDefinedCanon(varname string) bool

func (*VarTypeRegistry) IsDefinedExact

func (reg *VarTypeRegistry) IsDefinedExact(varname string) bool

type VarUseContext

type VarUseContext struct {
	IsWordPart bool // Example: LOCALBASE=${LOCALBASE}
	// contains filtered or unexported fields
}

VarUseContext defines the context in which a variable is defined or used. Whether that is allowed depends on:

* The variable's data type, as defined in vardefs.go.

* When used on the right-hand side of an assigment, the variable can represent a list of words, a single word or even only part of a word. This distinction decides upon the correct use of the :Q operator.

* When used in preprocessing statements like .if or .for, the other operands of that statement should fit to the variable and are checked against the variable type. For example, comparing OPSYS to x86_64 doesn't make sense.

func (*VarUseContext) String

func (vuc *VarUseContext) String() string

type VaralignBlock

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

VaralignBlock checks that all variable assignments from a paragraph use the same indentation depth for their values. It also checks that the indentation uses tabs instead of spaces.

In general, all values should be aligned using tabs. As an exception, a single very long line (called an outlier) may be aligned with a single space. A typical example is a SITES.very-long-file-name.tar.gz variable between HOMEPAGE and DISTFILES.

Continuation lines are also aligned to the single-line assignments. There are two types of continuation lines. The first type has just the continuation backslash in the first line:

MULTI_LINE= \
        The value starts in the second line.

The backslash in the first line is usually aligned to the other variables in the same paragraph. If the variable name is longer than the indentation of the paragraph, it may be indented with a single space. In multi-line shell commands or AWK programs, the backslash is often indented to column 73, as are the backslashes from the follow-up lines, to act as a visual guideline.

The indentation of the first value of the variable determines the minimum indentation for the remaining continuation lines. To allow long variable values to be indented as little as possible, the follow-up lines only need to be indented by a single tab, even if the other variables in the paragraph are aligned further to the right. If the indentation is not a single tab, it must match the indentation of the other lines in the paragraph.

MULTI_LINE=     The value starts in the first line \
                and continues in the second line.

In lists or plain text, like in the example above, all values are aligned in the same column. Some variables also contain code, and in these variables, the line containing the first word defines how deep the follow-up lines must be indented at least.

SHELL_CMD=                                                              \
        if ${PKG_ADMIN} pmatch ${PKGNAME} ${dependency}; then           \
                ${ECHO} yes;                                            \
        else                                                            \
                ${ECHO} no;                                             \
        fi

In the continuation lines, each follow-up line is indented with at least one tab, to avoid confusing them with regular single-lines. This is especially true for CONFIGURE_ENV, since the environment variables are typically uppercase as well.

For the purpose of aligning the variable assignments, each raw line is split into several parts, as described by the varalignParts type.

The alignment checks are performed on the raw lines instead of the logical lines, since this check is about the visual appearance as opposed to the meaning of the variable assignment.

FIXME: Implement each requirement from the above documentation.

Next try for the spec, from November 2019. Completely built from the existing examples, striving to be short and clear. Needs some more time to mature. After implementing it, it will be translated into English.

Ebenen: Datei > Absatz > MkZeile > Zeile

### Datei

#.  Ein einzelner Absatz, der einen Tab weniger eingerückt ist als die übrigen,
    darf auf die Einrückung der anderen Absätze angeglichen werden,
    sofern der Absatz dadurch nicht zu breit wird.

### Einzelner Absatz

#.  Jede Zeile besteht aus #, VarOp, Leerraum, Wert, Leerraum und Fortsetzung.

#.  Die Werte aller Zeilen sind mit Tabs an einer gemeinsamen vertikalen Linie
    (Ausrichtung) ausgerichtet.

#.  Das Ausrichten mit mehr als 1 Tab ist erlaubt, wenn die Ausrichtung einheitlich ist.

#.  Wenn VarOp über die Ausrichtung hinausragt (Ausreißer),
    darf zwischen VarOp und Wert statt der Ausrichtung 1 Leerzeichen sein.

#.  Die minimale Ausrichtung ergibt sich aus der maximalen Breite von # und VarOp
    aller Zeilen, gerundet zum nächsten Tabstopp.
    Dabei zählen auch Zeilen mit, die rechts von VarOp komplett leer sind.

#.  Die maximale Ausrichtung ergibt sich aus der maximalen Breite von Wert
    und Kommentar, abgezogen vom maximalen rechten Rand (in Spalte 73).

#.  Beim Umformatieren darf die Zeilenbreite die 73 Zeichen nicht überschreiten,
    damit am rechten Rand eindeutig ist, wo jede Zeile aufhört.
    Zeilen, die bereits vorher breiter waren, dürfen ruhig noch breiter werden.

#.  Das Verhältnis zwischen Tab-Zeilen und hinausragenden Zeilen muss ausgewogen sein.
    Nicht zu viele hinausragende Zeilen. (Noch zu definieren.)
    Möglicher Ansatz: Anteil der Leerfläche?

### Mehrzeilig

#.  Jede MkZeile hat für alle ihre Zeilen einen gemeinsamen rechten Rand.

#.  Die Fortsetzungen jeder MkZeile sind entweder alle durch je 1 Leerzeichen abgetrennt,
    oder alle Fortsetzungen sind am rechten Rand.

#.  Um den gemeinsamen rechten Rand zu bestimmen, werden alle Zeilen ignoriert,
    in denen die Fortsetzung durch 1 Leerzeichen abgetrennt ist.

#.  Einzelne Fortsetzungen dürfen über den rechten Rand hinausragen.
    Die Fortsetzung wird dann durch 1 Leerzeichen abgetrennt.

### Mehrzeilig, Erstzeile

#.  Die Fortsetzung der Erstzeile ist durch 1 Leerzeichen abgetrennt,
    wenn sie rechts von der Ausrichtung steht,
    andernfalls durch Tabs an der Ausrichtung.

#.  Eine leere Erstzeile mit 1 fortgesetzer Zeile ist nur zulässig,
    wenn die kombinierte Zeile breiter als 73 Zeichen wäre.
    Sonst werden die beiden Zeilen kombiniert.

### Mehrzeilig, fortgesetzte Zeilen

#.  Nach einer leeren Erstzeile ist die erste fortgesetzte Zeile an der
    Ausrichtung aller Zeilen eingerückt, wenn die Erstzeile über die
    Ausrichtung ragt und der Platz aller Zeilen es zulässt, andernfalls
    mit 1 Tab.

#.  Bei mehrzeiligen einrückbaren Werten (AWK, Shell, Listen aus Tupeln)
    dürfen die weiteren Fortsetzungszeilen weiter eingerückt sein als die erste.
    Ihre Einrückung besteht aus Tabs, gefolgt von 0 bis 7 Leerzeichen.

func (*VaralignBlock) Finish

func (va *VaralignBlock) Finish()

func (*VaralignBlock) Process

func (va *VaralignBlock) Process(mkline *MkLine)

type VaralignSplitter

type VaralignSplitter struct {
}

VaralignSplitter parses the text of a raw line into those parts that are relevant for aligning the variable values, and the backslash continuation markers.

See MkLineParser.unescapeComment for very similar code.

func NewVaralignSplitter

func NewVaralignSplitter() VaralignSplitter

type VargroupsChecker

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

VargroupsChecker checks that the _VARGROUPS section of an infrastructure file matches the rest of the file content:

- All variables that are used in the file should also be declared as used.

- All variables that are declared to be used should actually be used.

See mk/misc/show.mk, keyword _VARGROUPS.

func NewVargroupsChecker

func NewVargroupsChecker(mklines *MkLines) *VargroupsChecker

func (*VargroupsChecker) Check

func (ck *VargroupsChecker) Check(mkline *MkLine)

CheckVargroups checks that each variable that is used or defined somewhere in the file is also registered in the _VARGROUPS section, in order to make it discoverable by "bmake show-all".

This check is intended mainly for infrastructure files and similar support files, such as lang/*/module.mk.

func (*VargroupsChecker) Finish

func (ck *VargroupsChecker) Finish()

type Vartype

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

Vartype is a combination of a data type and a permission specification. See vardefs.go for examples, and vartypecheck.go for the implementation.

func NewVartype

func NewVartype(basicType *BasicType, options vartypeOptions, aclEntries ...ACLEntry) *Vartype

func (*Vartype) AlternativeFiles

func (vt *Vartype) AlternativeFiles(perms ACLPermissions) string

AlternativeFiles lists the file patterns in which all of the given permissions are allowed, readily formatted to be used in a diagnostic.

If the permission is allowed nowhere, an empty string is returned.

func (*Vartype) EffectivePermissions

func (vt *Vartype) EffectivePermissions(basename RelPath) ACLPermissions

func (*Vartype) IsAlwaysInScope

func (vt *Vartype) IsAlwaysInScope() bool

func (*Vartype) IsCommandLineProvided

func (vt *Vartype) IsCommandLineProvided() bool

func (*Vartype) IsDefinedIfInScope

func (vt *Vartype) IsDefinedIfInScope() bool

func (*Vartype) IsGuessed

func (vt *Vartype) IsGuessed() bool

func (*Vartype) IsList

func (vt *Vartype) IsList() bool

func (*Vartype) IsNonemptyIfDefined

func (vt *Vartype) IsNonemptyIfDefined() bool

func (*Vartype) IsOnePerLine

func (vt *Vartype) IsOnePerLine() bool

func (*Vartype) IsPackageSettable

func (vt *Vartype) IsPackageSettable() bool

func (*Vartype) IsShell

func (vt *Vartype) IsShell() bool

func (*Vartype) IsSystemProvided

func (vt *Vartype) IsSystemProvided() bool

func (*Vartype) IsUnique

func (vt *Vartype) IsUnique() bool

func (*Vartype) IsUserSettable

func (vt *Vartype) IsUserSettable() bool

func (*Vartype) MayBeAppendedTo

func (vt *Vartype) MayBeAppendedTo() bool

func (*Vartype) NeedsRationale

func (vt *Vartype) NeedsRationale() bool

func (*Vartype) String

func (vt *Vartype) String() string

func (*Vartype) Union

func (vt *Vartype) Union() ACLPermissions

Union returns the union of all possible permissions. This can be used to check whether a variable may be defined or used at all, or if it is read-only.

type VartypeCheck

type VartypeCheck struct {
	MkLines *MkLines
	MkLine  *MkLine

	// The name of the variable being checked.
	//
	// In some cases (see WithVarnameValueMatch) it contains not the
	// variable name but more a "description" of a part of a variable.
	// See MachinePlatform for an example.
	Varname    string
	Op         MkOperator
	Value      string
	ValueNoVar string
	MkComment  string // The comment including the "#".
	Guessed    bool   // Whether the type definition is guessed (based on the variable name) or explicitly defined (see vardefs.go).
}

VartypeCheck groups together the various checks for variables of the different types.

func (*VartypeCheck) Autofix

func (cv *VartypeCheck) Autofix() *Autofix

Autofix returns the autofix instance belonging to the line.

Usage:

fix := cv.Autofix()

fix.Errorf("Must not be ...")
fix.Warnf("Should not be ...")
fix.Notef("It is also possible ...")

fix.Explain(
    "Explanation ...",
    "... end of explanation.")

fix.Replace("from", "to")
fix.ReplaceAfter("prefix", "from", "to")
fix.InsertAbove("new line")
fix.InsertBelow("new line")
fix.Delete()
fix.Custom(func(showAutofix, autofix bool) {})

fix.Apply()

func (*VartypeCheck) AwkCommand

func (cv *VartypeCheck) AwkCommand()

func (*VartypeCheck) BasicRegularExpression

func (cv *VartypeCheck) BasicRegularExpression()

BasicRegularExpression checks for a basic regular expression, as defined by POSIX.

When they are used in a list variable (as for CHECK_FILES_SKIP), they cannot include spaces. Instead, a dot or [[:space:]] must be used. The regular expressions do not need any quotation for the shell; all quoting issues are handled by the pkgsrc infrastructure.

The opposite situation is when the regular expression is part of a sed command. In such a case the shell quoting is undone before checking the regular expression, and this is where spaces and tabs can appear.

TODO: Add check for EREs as well.

See https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_03. See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03.

func (*VartypeCheck) BuildlinkDepmethod

func (cv *VartypeCheck) BuildlinkDepmethod()

func (*VartypeCheck) CFlag

func (cv *VartypeCheck) CFlag()

CFlag is a single option to the C/C++ compiler.

func (*VartypeCheck) Category

func (cv *VartypeCheck) Category()

func (*VartypeCheck) Comment

func (cv *VartypeCheck) Comment()

Comment checks for the single-line description of a package.

The comment for categories is checked in CheckdirCategory since these almost never change.

func (*VartypeCheck) ConfFiles

func (cv *VartypeCheck) ConfFiles()

ConfFiles checks pairs of example file, configuration file.

When a package is installed, the example file is installed as usual and is then copied to its final location.

func (*VartypeCheck) DependencyPattern

func (cv *VartypeCheck) DependencyPattern()

func (*VartypeCheck) DependencyWithPath

func (cv *VartypeCheck) DependencyWithPath()

func (*VartypeCheck) DistSuffix

func (cv *VartypeCheck) DistSuffix()

func (*VartypeCheck) EmulPlatform

func (cv *VartypeCheck) EmulPlatform()

func (*VartypeCheck) Enum

func (cv *VartypeCheck) Enum(allowedValues map[string]bool, basicType *BasicType)

Enum checks an enumeration for valid values.

The given allowedValues contains all allowed enum values. The given basicType is only provided to lazily access the allowed enum values as a sorted list.

func (*VartypeCheck) Errorf

func (cv *VartypeCheck) Errorf(format string, args ...interface{})

func (*VartypeCheck) Explain

func (cv *VartypeCheck) Explain(explanation ...string)

func (*VartypeCheck) FetchURL

func (cv *VartypeCheck) FetchURL()

func (*VartypeCheck) FileMode

func (cv *VartypeCheck) FileMode()

func (*VartypeCheck) FilePattern

func (cv *VartypeCheck) FilePattern()

func (*VartypeCheck) Filename

func (cv *VartypeCheck) Filename()

Filename checks that filenames use only limited special characters.

See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_169

func (*VartypeCheck) GccReqd

func (cv *VartypeCheck) GccReqd()

func (*VartypeCheck) Homepage

func (cv *VartypeCheck) Homepage()

func (*VartypeCheck) IdentifierDirect

func (cv *VartypeCheck) IdentifierDirect()

Identifier checks for valid identifiers in various contexts, limiting the valid characters to A-Za-z0-9_.

func (*VartypeCheck) IdentifierIndirect

func (cv *VartypeCheck) IdentifierIndirect()

Identifier checks for valid identifiers in various contexts, limiting the valid characters to A-Za-z0-9_.

func (*VartypeCheck) Integer

func (cv *VartypeCheck) Integer()

func (*VartypeCheck) LdFlag

func (cv *VartypeCheck) LdFlag()

func (*VartypeCheck) License

func (cv *VartypeCheck) License()

func (*VartypeCheck) MachineGnuPlatform

func (cv *VartypeCheck) MachineGnuPlatform()

func (*VartypeCheck) MachinePlatform

func (cv *VartypeCheck) MachinePlatform()

func (*VartypeCheck) MachinePlatformPattern

func (cv *VartypeCheck) MachinePlatformPattern()

func (*VartypeCheck) MailAddress

func (cv *VartypeCheck) MailAddress()

func (*VartypeCheck) Message

func (cv *VartypeCheck) Message()

Message is a plain string. When defining a message variable, it should not be enclosed in quotes since that is the job of the code that uses the message.

Lists of messages use a different type since they need the quotes around each message; see PKG_FAIL_REASON.

func (*VartypeCheck) Notef

func (cv *VartypeCheck) Notef(format string, args ...interface{})

func (*VartypeCheck) Option

func (cv *VartypeCheck) Option()

Option checks whether a single package option from an options.mk file conforms to the naming conventions.

This check only handles option names, as in PKG_SUPPORTED_OPTIONS or PKG_SUGGESTED_OPTIONS. It does not handle option selections, which may pre prefixed with a hyphen to disable the option. Option selections are all user-settable and therefore are out of scope for pkglint.

func (*VartypeCheck) PathPattern

func (cv *VartypeCheck) PathPattern()

PathPattern is a shell pattern for pathnames, possibly including slashes.

See FilePattern.

func (*VartypeCheck) Pathlist

func (cv *VartypeCheck) Pathlist()

Pathlist checks variables like the PATH environment variable.

func (*VartypeCheck) Pathname

func (cv *VartypeCheck) Pathname()

Pathname checks for pathnames.

Like Filename, but including slashes.

See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_266

func (*VartypeCheck) PathnameSpace

func (cv *VartypeCheck) PathnameSpace()

Like Pathname, but may contain spaces as well. Because the spaces must be quoted, backslashes and quotes are allowed as well.

func (*VartypeCheck) Perl5Packlist

func (cv *VartypeCheck) Perl5Packlist()

func (*VartypeCheck) Perms

func (cv *VartypeCheck) Perms()

func (*VartypeCheck) PkgOptionsVar

func (cv *VartypeCheck) PkgOptionsVar()

func (*VartypeCheck) Pkgname

func (cv *VartypeCheck) Pkgname()

func (*VartypeCheck) Pkgpath

func (cv *VartypeCheck) Pkgpath()

Pkgpath checks a directory name relative to the top-level pkgsrc directory.

Despite its name, it is more similar to RelativePkgDir than to RelativePkgPath.

func (*VartypeCheck) Pkgrevision

func (cv *VartypeCheck) Pkgrevision()

func (*VartypeCheck) PlistIdentifier

func (cv *VartypeCheck) PlistIdentifier()

PlistIdentifier checks for valid condition identifiers in PLIST_VARS.

These identifiers are interpreted as regular expressions by mk/plist/plist-subst.mk, therefore they are limited to very few characters.

func (*VartypeCheck) PrefixPathname

func (cv *VartypeCheck) PrefixPathname()

PrefixPathname checks for a pathname relative to ${PREFIX}.

func (*VartypeCheck) PythonDependency

func (cv *VartypeCheck) PythonDependency()

func (*VartypeCheck) RPkgName

func (cv *VartypeCheck) RPkgName()

func (*VartypeCheck) RPkgVer

func (cv *VartypeCheck) RPkgVer()

func (*VartypeCheck) RelativePkgDir

func (cv *VartypeCheck) RelativePkgDir()

RelativePkgDir refers from one package directory to another package directory, e.g. ../../category/pkgbase.

func (*VartypeCheck) RelativePkgPath

func (cv *VartypeCheck) RelativePkgPath()

RelativePkgPath refers from one package directory to another file or directory, e.g. ../../category/pkgbase, ../../category/pkgbase/Makefile.

See RelativePkgDir, which requires a directory, not a file.

func (*VartypeCheck) Restricted

func (cv *VartypeCheck) Restricted()

func (*VartypeCheck) SedCommands

func (cv *VartypeCheck) SedCommands()

func (*VartypeCheck) ShellCommand

func (cv *VartypeCheck) ShellCommand()

func (*VartypeCheck) ShellCommands

func (cv *VartypeCheck) ShellCommands()

ShellCommands checks for zero or more shell commands, each terminated with a semicolon.

func (*VartypeCheck) ShellWord

func (cv *VartypeCheck) ShellWord()

func (*VartypeCheck) Stage

func (cv *VartypeCheck) Stage()

func (*VartypeCheck) ToolDependency

func (cv *VartypeCheck) ToolDependency()

ToolDependency checks for tool dependencies like "awk", "m4:pkgsrc", "digest:bootstrap".

func (*VartypeCheck) ToolName

func (cv *VartypeCheck) ToolName()

ToolName checks for a tool name without any trailing ":pkgsrc" or ":run".

func (*VartypeCheck) URL

func (cv *VartypeCheck) URL()

func (*VartypeCheck) Unknown

func (cv *VartypeCheck) Unknown()

Unknown doesn't check for anything.

Used for:

  • infrastructure variables that are not in vardefs.go
  • other variables whose type is unknown or not interesting enough to warrant the creation of a specialized type

func (*VartypeCheck) UserGroupName

func (cv *VartypeCheck) UserGroupName()

func (*VartypeCheck) VariableName

func (cv *VartypeCheck) VariableName()

VariableName checks that the value is a valid variable name to be used in Makefiles.

func (*VartypeCheck) VariableNamePattern

func (cv *VartypeCheck) VariableNamePattern()

func (*VartypeCheck) Version

func (cv *VartypeCheck) Version()

func (*VartypeCheck) Warnf

func (cv *VartypeCheck) Warnf(format string, args ...interface{})

func (*VartypeCheck) WithValue

func (cv *VartypeCheck) WithValue(value string) *VartypeCheck

WithValue returns a new VartypeCheck context by copying all fields except the value.

This is typically used when calling a related check.

func (*VartypeCheck) WithVarnameValue

func (cv *VartypeCheck) WithVarnameValue(varname, value string) *VartypeCheck

WithVarnameValue returns a new VartypeCheck context by copying all fields except the variable name and the value.

This is typically used when checking parts of composite types.

func (*VartypeCheck) WithVarnameValueMatch

func (cv *VartypeCheck) WithVarnameValueMatch(varname, value string) *VartypeCheck

WithVarnameValueMatch returns a new VartypeCheck context by copying all fields except the variable name, the operator (it is set to opUseMatch) and the value.

This is typically used when checking parts of composite types, such as the patterns from ONLY_FOR_PLATFORM.

func (*VartypeCheck) WrapperReorder

func (cv *VartypeCheck) WrapperReorder()

func (*VartypeCheck) WrapperTransform

func (cv *VartypeCheck) WrapperTransform()

func (*VartypeCheck) WrkdirSubdirectory

func (cv *VartypeCheck) WrkdirSubdirectory()

func (*VartypeCheck) WrksrcPathPattern

func (cv *VartypeCheck) WrksrcPathPattern()

WrksrcPathPattern is a shell pattern for existing pathnames, possibly including slashes.

func (*VartypeCheck) WrksrcSubdirectory

func (cv *VartypeCheck) WrksrcSubdirectory()

WrksrcSubdirectory checks a directory relative to ${WRKSRC}, for use in CONFIGURE_DIRS and similar variables.

func (*VartypeCheck) Yes

func (cv *VartypeCheck) Yes()

func (*VartypeCheck) YesNo

func (cv *VartypeCheck) YesNo()

YesNo checks for variables that can be set to either yes or no. Undefined means no.

Most of these variables use the lowercase yes/no variant. Some use the uppercase YES/NO, and the mixed forms Yes/No are practically never seen. Testing these variables using the however-mixed pattern is done solely because writing this pattern is shorter than repeating the variable name.

func (*VartypeCheck) YesNoIndirectly

func (cv *VartypeCheck) YesNoIndirectly()

type VucQuoting

type VucQuoting uint8

VucQuoting describes in what level of quoting the variable is used. Depending on this context, the modifiers :Q or :M can be allowed or not.

The shell tokenizer knows multi-level quoting modes (see ShQuoting), but for deciding whether :Q is necessary or not, a single level is enough.

const (
	VucQuotUnknown VucQuoting = iota
	VucQuotPlain              // Example: echo LOCALBASE=${LOCALBASE}
	VucQuotDquot              // Example: echo "The version is ${PKGVERSION}."
	VucQuotSquot              // Example: echo 'The version is ${PKGVERSION}.'
	VucQuotBackt              // Example: echo `sed 1q ${WRKSRC}/README`
)

func (VucQuoting) String

func (q VucQuoting) String() string

type VucTime

type VucTime uint8

VucTime is the time at which a variable is used.

See ToolTime, which is the same except that there is no unknown.

const (
	VucUnknownTime VucTime = iota

	// VucLoadTime marks a variable use that happens directly when
	// the Makefile fragment is loaded.
	//
	// When Makefiles are loaded, the operators := and != evaluate their
	// right-hand side, as well as the directives .if, .elif and .for.
	// During loading, not all variables are available yet.
	// Variable values are still subject to change, especially lists.
	VucLoadTime

	// VucRunTime marks a variable use that happens after all files have been loaded.
	//
	// At this time, all variables can be referenced.
	//
	// At this time, variable values don't change anymore.
	// Well, except for the ::= modifier.
	// But that modifier is usually not used in pkgsrc.
	VucRunTime
)

func (VucTime) String

func (t VucTime) String() string

type YesNoUnknown

type YesNoUnknown uint8

func (YesNoUnknown) String

func (ynu YesNoUnknown) String() string

Directories

Path Synopsis
cmd
Package getopt provides a parser for command line options, supporting multi-value options such as -Wall,no-extra.
Package getopt provides a parser for command line options, supporting multi-value options such as -Wall,no-extra.
Package intqa provides quality assurance for the pkglint code.
Package intqa provides quality assurance for the pkglint code.
Package regex provides a registry of precompiled regular expressions to allow reusing them without the syntactic overhead of declaring pattern variables everywhere in the code.
Package regex provides a registry of precompiled regular expressions to allow reusing them without the syntactic overhead of declaring pattern variables everywhere in the code.
Package trace traces function calls and steps in-between.
Package trace traces function calls and steps in-between.

Jump to

Keyboard shortcuts

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