spec

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNoSuchTag = errors.New("no such tag")

ErrNoSuchTag is returned when a requested tag does not exist in the spec.

View Source
var ErrPatternNotFound = errors.New("pattern not found")

ErrPatternNotFound is returned when a search pattern does not match any content in the spec.

View Source
var ErrSectionNotFound = errors.New("section not found")

ErrSectionNotFound is returned when a requested section does not exist in the spec.

Functions

func GetPackageNameFromSectionHeader

func GetPackageNameFromSectionHeader(tokens []string) string

GetPackageNameFromSectionHeader extracts the package name from the tokens of a section header line. For example, for a line like "%package -n foo", it would return "foo". For a line like "%package foo", it would return "foo" as well. Because this function does not know the base name of the spec, it cannot take a suffix-only name and resolve it to a full name.

func ParsePatchTagNumber

func ParsePatchTagNumber(tag string) (int, bool)

ParsePatchTagNumber checks if the given tag name is a PatchN tag (case-insensitive) and returns the numeric suffix N. Returns -1, false if the tag is not a PatchN tag or the suffix is not a valid integer.

Types

type Context

type Context struct {
	// Target is the current visit target.
	Target VisitTarget
	// RawLine is the raw text of the current line, if applicable (nil otherwise).
	RawLine *string
	// CurrentSection is the current section being visited.
	CurrentSection SectionTarget
	// CurrentLineNum is the current (0-indexed) line number being visited.
	CurrentLineNum int
	// contains filtered or unexported fields
}

Context provides context information to a visitor function when visiting a spec.

func (*Context) InsertLinesAfter

func (ctx *Context) InsertLinesAfter(lines []string)

InsertLinesAfter inserts the provided lines just after the line currently being visited, updating the context accordingly. The next line to be visited will be the line following the newly inserted lines.

func (*Context) InsertLinesBefore

func (ctx *Context) InsertLinesBefore(lines []string)

InsertLinesBefore inserts the provided lines just before the line currently being visited, updating the context accordingly. The next line to be visited will be the line following the current one being visited.

func (*Context) RemoveLine

func (ctx *Context) RemoveLine()

RemoveLine removes the line currently being visited, updating the context accordingly. The next line to be visited will be the line that followed the removed line.

func (*Context) ReplaceLine

func (ctx *Context) ReplaceLine(replacement string)

ReplaceLine replaces the line currently being visited with the provided replacement line, updating the context accordingly.

type Line

type Line struct {
	// Text is the original physical text of the line.
	Text string
	// Parsed is the parsed representation of the line's contents.
	Parsed ParsedLine
}

Line represents a single line in an RPM spec file.

type ParsedLine

type ParsedLine interface {
	// GetType returns the type of the parsed line.
	GetType() ParsedLineType
}

ParsedLine is the interface that all parsed line types implement.

type ParsedLineType

type ParsedLineType string

ParsedLineType represents the type of a parsed line.

const (
	// SectionStart applies to lines that start a new section, e.g. "%description".
	SectionStart ParsedLineType = "SectionStart"
	// Tag applies to lines that define a tag, e.g. "Name: foo".
	Tag ParsedLineType = "Tag"
	// Raw applies to lines that are raw text, e.g. a line in a script section.
	Raw ParsedLineType = "Raw"
)

type RawLine

type RawLine struct {
	// Content is the raw line text.
	Content string
}

RawLine represents a line that is raw text.

func (*RawLine) GetType

func (*RawLine) GetType() ParsedLineType

GetType returns the type of the parsed line.

type SectionStartLine

type SectionStartLine struct {
	SectType SectionType
	SectName string
	Tokens   []string
}

SectionStartLine represents a line that starts a new section in the spec, e.g.: "%build".

func (*SectionStartLine) GetType

func (*SectionStartLine) GetType() ParsedLineType

GetType returns the type of the parsed line.

type SectionTarget

type SectionTarget struct {
	// SectName is the name of the section, e.g. "%description".
	SectName string
	// SectType is the type of the section.
	SectType SectionType
	// Package is the package this section applies to, if any. Left empty for
	// the default package or sections that aren't package-specific.
	Package string
}

SectionTarget encapsulates information about the current section context.

type SectionType

type SectionType string

SectionType represents the type of a section in an RPM spec file.

const (
	// PackageSection applies to sections that define a package, e.g. "%package -n foo".
	PackageSection SectionType = "Package"
	// ScriptSection applies to sections that contain scripts, e.g. "%build".
	ScriptSection SectionType = "Script"
	// RawSection applies to sections that contain raw content, e.g.: "%description".
	RawSection SectionType = "Raw"
	// ChangelogSection applies to the "%changelog" section.
	ChangelogSection SectionType = "Changelog"
	// FilesSection applies to a "%files" section.
	FilesSection SectionType = "Files"
	// SourceFileListSection applies to a section that lists source files, e.g.: "%sourcelist".
	SourceFileListSection SectionType = "SourceFileList"
)

type Spec

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

Spec encapsulates the contents of an RPM spec file.

func OpenSpec

func OpenSpec(reader io.Reader) (*Spec, error)

OpenSpec reads in the contents of an RPM spec file from the provided reader, returning a Spec object. An error is returned if the reader cannot be fully read (e.g., I/O error or line exceeds buffer size).

func (*Spec) AddChangelogEntry

func (s *Spec) AddChangelogEntry(user, email, version, release string, time time.Time, details []string) (err error)

AddChangelogEntry adds a changelog entry to the spec's changelog section. An error is returned if no %changelog section exists in the spec.

func (*Spec) AddPatchEntry

func (s *Spec) AddPatchEntry(packageName, filename string) error

AddPatchEntry registers a patch in the spec, either by appending to an existing %patchlist section or by adding a new PatchN tag with the next available number. Returns an error if the spec cannot be examined or updated.

func (*Spec) AddTag

func (s *Spec) AddTag(packageName string, tag string, value string) (err error)

AddTag adds the given tag to the spec, under the specified package (or globally if `packageName` is empty). This function will indiscriminately add the tag and does not first check to see if any instances of this tag already exist in the indicated package. This is useful for tags that can appear multiple times, or in cases in which a determination has already been made that a singleton tag in question doesn't already exist.

Note: When adding to a sub-package (non-empty packageName), the corresponding %package section must already exist in the spec; otherwise, an ErrSectionNotFound error is returned.

func (*Spec) AppendLinesToSection

func (s *Spec) AppendLinesToSection(sectionName, packageName string, lines []string) (err error)

AppendLinesToSection appends the given lines at the end of the specified section, placing them just after the current last line of the section. An error is returned if the identified section cannot be found in the spec.

func (*Spec) GetHighestPatchTagNumber

func (s *Spec) GetHighestPatchTagNumber(packageName string) (int, error)

GetHighestPatchTagNumber scans the spec for all PatchN tags (where N is a decimal number) in the given package and returns the highest N found. Returns -1 if no numeric patch tags exist. Tags with non-numeric suffixes (e.g., macro-based names like Patch%{n}) are silently skipped.

func (*Spec) HasSection

func (s *Spec) HasSection(sectionName string) (bool, error)

HasSection returns true if the spec contains a section with the given name. The comparison is exact (case-sensitive), consistent with [AppendLinesToSection].

func (*Spec) InsertLinesAt

func (s *Spec) InsertLinesAt(insertedLines []string, lineNumber int)

InsertLinesAt inserts the provided lines just before the specified (0-indexed) line number.

func (*Spec) InsertTag

func (s *Spec) InsertTag(packageName string, tag string, value string) error

InsertTag inserts a tag into the spec, placing it after the last existing tag from the same "family" (e.g., Source9999 is placed after the last Source* tag). If no tags from the same family exist, the tag is placed after the last tag of any kind. If there are no tags at all, it falls back to [AddTag] behavior (appending to the section end).

The tag family is determined by stripping trailing digits from the tag name (case-insensitive). For example, "Source0", "Source1", and "Source" all belong to the "source" family.

If the chosen insertion point falls inside a conditional block (%if/%endif), the tag is placed after the closing %endif instead, so it remains unconditional.

Note: When inserting into a sub-package (non-empty packageName), the corresponding %package section must already exist in the spec; otherwise, an ErrSectionNotFound error is returned.

func (*Spec) PrependLinesToSection

func (s *Spec) PrependLinesToSection(sectionName, packageName string, lines []string) (err error)

PrependLinesToSection prepends the given lines to the start of the specified section, placing them just after the section header (or at the top of the file in the global section). An error is returned if the identified section cannot be found in the spec.

func (*Spec) RemoveLine

func (s *Spec) RemoveLine(lineNumber int)

RemoveLine removes the line at the specified (0-indexed) line number.

func (*Spec) RemovePatchEntry

func (s *Spec) RemovePatchEntry(packageName, pattern string) error

RemovePatchEntry removes all references to patches matching the given pattern from the spec. The pattern is a glob pattern (supporting doublestar syntax) matched against PatchN tag values and %patchlist entries. Returns an error if no references matched the pattern.

func (*Spec) RemoveTag

func (s *Spec) RemoveTag(packageName string, tag string, value string) (err error)

RemoveTag removes all instances of the given tag from the spec, under the specified package (or globally if `packageName` is empty). If the provided `value` is non-empty, then only tag instances whose values are as specified will be removed. This function returns an error if a tag matching those criteria did not exist in the given package.

func (*Spec) RemoveTagsMatching

func (s *Spec) RemoveTagsMatching(packageName string, matcher func(tag, value string) bool) (int, error)

RemoveTagsMatching removes all tags in the given package for which the provided matcher function returns true. The matcher receives the tag name and value as arguments. Returns the number of tags removed. If no matching tags were found, returns 0 and no error.

func (*Spec) ReplaceLine

func (s *Spec) ReplaceLine(lineNumber int, replacement string)

ReplaceLine replaces the line at the specified (0-indexed) line number with the provided replacement line.

func (*Spec) SearchAndReplace

func (s *Spec) SearchAndReplace(sectionName, packageName, regex, replacement string) (err error)

SearchAndReplace performs a regex-based search-and-replace against all lines in the specified section. If `sectionName` is empty, the operation acts against all sections. If no matches were found to replace, an error is returned. The replacement is performed literally; regex capture group references like $1 are not expanded.

func (*Spec) Serialize

func (s *Spec) Serialize(writer io.Writer) error

Serialize writes the spec's contents to the provided writer.

func (*Spec) SetTag

func (s *Spec) SetTag(packageName string, tag string, value string) (err error)

SetTag sets the value of the given tag in the spec, under the specified package. It first attempts to update the first instance of the tag found in the spec; if no such tag exists, a new tag is added under the given package.

func (*Spec) UpdateExistingTag

func (s *Spec) UpdateExistingTag(packageName string, tag string, value string) (err error)

UpdateExistingTag looks for the first instance of the named tag in the given package; if it finds such a tag instance, it replaces its value with the provided value. If no such tag exists, it returns an error.

func (*Spec) Visit

func (s *Spec) Visit(visitor Visitor) error

Visit walks through the spec, invoking the provided visitor function for each relevant target.

State Management Invariants:

  • nextLineNumToParse: The next 0-indexed line number to parse. May be less than or equal to CurrentLineNum when context mutations (InsertLinesBefore, RemoveLine, ReplaceLine) require re-parsing the current position.
  • nextLineNumToVisit: The next 0-indexed line number to send to the visitor. A line is visited only if CurrentLineNum >= nextLineNumToVisit, allowing mutations to skip visiting newly inserted lines or re-visit lines after removal.
  • Context mutation methods update these values to maintain correct traversal after modifications.

func (*Spec) VisitTags

func (s *Spec) VisitTags(packageName string, visitor func(tagLine *TagLine, ctx *Context) error) error

VisitTags iterates over all tag lines in the given package, calling the visitor function for each one. The visitor receives the parsed TagLine and the mutation Context. This extracts the common target-type / package / tag-type filtering that many tag-oriented methods need.

type TagLine

type TagLine struct {
	// Tag is the name of the tag being defined.
	Tag string
	// Value is the value assigned to the tag.
	Value string
}

TagLine encapsulates the definition of a tag.

func (*TagLine) GetType

func (*TagLine) GetType() ParsedLineType

GetType returns the type of the parsed line.

type VisitTarget

type VisitTarget struct {
	// TargetType is the type of the current visit target.
	TargetType VisitTargetType
	// Optionally, provides more detail about the target's section.
	// Left nil when the target is not part of a section.
	Section *SectionTarget
	// Optionally, provides more detail about the target's line. Left nil
	// when the target is not a line.
	Line *Line
}

VisitTarget encapsulates the current target of a visit operation.

type VisitTargetType

type VisitTargetType string

VisitTargetType indicates the type of a visit target.

const (
	// SpecStartTarget indicates the start of the spec.
	SpecStartTarget VisitTargetType = "SpecStart"
	// SectionStartTarget indicates the start of a section.
	SectionStartTarget VisitTargetType = "SectionStart"
	// SectionLineTarget indicates a line within a section.
	SectionLineTarget VisitTargetType = "SectionLine"
	// SectionEndTarget indicates the end of a section.
	SectionEndTarget VisitTargetType = "SectionEnd"
	// SpecEndTarget indicates the end of the spec.
	SpecEndTarget VisitTargetType = "SpecEnd"
)

type Visitor

type Visitor = func(ctx *Context) error

Visitor is the type of a visitor function that can be passed to Spec.Visit.

Jump to

Keyboard shortcuts

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