Documentation
¶
Overview ¶
Package gradlefile is a small parsing and editing library for the Gradle files omnibump needs to patch: build scripts (build.gradle, build.gradle.kts and other *.gradle(.kts) scripts such as gradle/dependencies.gradle), settings scripts with inline version catalogs, gradle.properties-style files, and gradle/libs.versions.toml version catalogs.
It is intentionally not a general Gradle DSL parser. Files are scanned for the version-bearing constructs omnibump understands, each construct is recorded with its source span, and edits are format-preserving splices at those spans: everything outside the edited value is preserved byte for byte. Both the Groovy and Kotlin DSL syntaxes are supported, selected by file extension.
The package performs no file I/O: callers pass content in and read content back via Content(). Path policy (size limits, symlink and root-boundary checks) belongs to the caller.
Index ¶
- Constants
- Variables
- func IsManagedClasspathName(name string) bool
- func IsNonShippingConfigName(name string) bool
- func NewSettingsFileContent(dsl DSL, constraints map[string]string, subs []Substitution) (string, error)
- func NewSettingsFileContentWithConfigs(dsl DSL, constraints map[string]string, subs []Substitution, ...) (string, error)
- func NormalizeAlias(alias string) string
- func ValidateCoordinate(coordinate string) error
- func ValidateModule(module string) error
- func ValidateVersion(version string) error
- type BuildFile
- func (f *BuildFile) ChangeCount() int
- func (f *BuildFile) Changed() bool
- func (f *BuildFile) Content() []byte
- func (f *BuildFile) DSL() DSL
- func (f *BuildFile) Dependencies() []DependencyDecl
- func (f *BuildFile) ForcedCoordinates() map[string]string
- func (f *BuildFile) Path() string
- func (f *BuildFile) ResolutionRules() []ResolutionRule
- func (f *BuildFile) SetDependencyVersion(d DependencyDecl, version string) error
- func (f *BuildFile) SetResolutionRuleVersion(r ResolutionRule, version string) error
- func (f *BuildFile) SetVariable(v VarDef, value string) error
- func (f *BuildFile) ShipConfigs() []ShipConfigRef
- func (f *BuildFile) Variables() []VarDef
- type CatalogFile
- func (f *CatalogFile) ChangeCount() int
- func (f *CatalogFile) Changed() bool
- func (f *CatalogFile) Content() []byte
- func (f *CatalogFile) Libraries() []CatalogLibrary
- func (f *CatalogFile) Path() string
- func (f *CatalogFile) SetLibraryVersion(lib CatalogLibrary, value string) error
- func (f *CatalogFile) SetVersion(key, value string) error
- func (f *CatalogFile) Versions() []CatalogVersion
- type CatalogLibrary
- type CatalogVersion
- type DSL
- type DeclKind
- type DependencyDecl
- type PropertiesFile
- func (f *PropertiesFile) ChangeCount() int
- func (f *PropertiesFile) Changed() bool
- func (f *PropertiesFile) Content() []byte
- func (f *PropertiesFile) Entries() []PropertyEntry
- func (f *PropertiesFile) Get(key string) (string, bool)
- func (f *PropertiesFile) Keys() []string
- func (f *PropertiesFile) Path() string
- func (f *PropertiesFile) Set(key, value string) error
- type PropertyEntry
- type ResolutionRule
- type SettingsFile
- func (f *SettingsFile) CatalogLibraries() []CatalogLibrary
- func (f *SettingsFile) CatalogVersions() []CatalogVersion
- func (f *SettingsFile) ChangeCount() int
- func (f *SettingsFile) Changed() bool
- func (f *SettingsFile) Content() []byte
- func (f *SettingsFile) DSL() DSL
- func (f *SettingsFile) EnsureManagedBlock(constraints map[string]string, subs []Substitution) error
- func (f *SettingsFile) EnsureManagedBlockWithConfigs(constraints map[string]string, subs []Substitution, extraConfigs []string) error
- func (f *SettingsFile) ManagedCoordinates() map[string]string
- func (f *SettingsFile) Path() string
- func (f *SettingsFile) SetCatalogVersion(c CatalogVersion, value string) error
- type ShipConfigRef
- type Substitution
- type VarDef
Examples ¶
- BuildFile.ResolutionRules
- BuildFile.SetDependencyVersion
- BuildFile.SetVariable
- BuildFile.ShipConfigs
- CatalogFile.SetLibraryVersion
- DSLFromPath
- IsManagedClasspathName
- IsNonShippingConfigName
- NewSettingsFileContent
- NewSettingsFileContentWithConfigs
- NormalizeAlias
- ParseBuild
- ParseCatalog
- ParseProperties
- ParseSettings
- SettingsFile.EnsureManagedBlock
- SettingsFile.EnsureManagedBlockWithConfigs
- ValidateCoordinate
- ValidateVersion
Constants ¶
const ( // ForceBlockBegin opens the managed block. ForceBlockBegin = "// omnibump:resolutionStrategy:begin" // ForceBlockEnd closes the managed block. ForceBlockEnd = "// omnibump:resolutionStrategy:end" )
Marker comments delimiting the omnibump-managed block. The block is hosted in the root settings script and pins transitive dependency versions (via dependency constraints) and coordinate swaps (via dependencySubstitution); re-running omnibump merges into the existing block instead of appending duplicates. See managed.go for the writer.
Variables ¶
var ( // ErrInvalidVersion is returned when a version string contains characters // outside the safe allowlist. The allowlist prevents code injection into // Gradle scripts through crafted version strings. ErrInvalidVersion = errors.New("invalid version string") // ErrInvalidCoordinate is returned when a group or artifact identifier // contains characters outside the safe allowlist. ErrInvalidCoordinate = errors.New("invalid coordinate") // ErrConflictingEdit is returned when two edits target the same or // overlapping source spans with different replacement values. ErrConflictingEdit = errors.New("conflicting edit") // ErrNotEditable is returned when an edit is requested on a construct the // library cannot rewrite in place (for example setting the version of a // declaration whose version is a variable reference). ErrNotEditable = errors.New("construct is not editable") )
Functions ¶
func IsManagedClasspathName ¶ added in v0.18.6
IsManagedClasspathName reports whether name is a compile/runtime classpath configuration already covered by the default managed match, so it need not be added to the extra ship-configuration list.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
fmt.Println(gradlefile.IsManagedClasspathName("testRuntimeClasspath"))
fmt.Println(gradlefile.IsManagedClasspathName("lineageImplementation"))
}
Output: true false
func IsNonShippingConfigName ¶ added in v0.18.6
IsNonShippingConfigName reports whether name denotes a documentation, lint, static-analysis or annotation-processing configuration whose dependencies do not ship at runtime, so it should be excluded from auto-detected ship configurations.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
fmt.Println(gradlefile.IsNonShippingConfigName("groovyDoc"))
fmt.Println(gradlefile.IsNonShippingConfigName("lineageImplementation"))
}
Output: true false
func NewSettingsFileContent ¶ added in v0.18.0
func NewSettingsFileContent(dsl DSL, constraints map[string]string, subs []Substitution) (string, error)
NewSettingsFileContent returns the content for a brand-new root settings script that exists only to host the managed block.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
content, err := gradlefile.NewSettingsFileContent(gradlefile.Kotlin, map[string]string{"a.b:c": "1.0"}, nil)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(content[:len(gradlefile.ForceBlockBegin)])
}
Output: // omnibump:resolutionStrategy:begin
func NewSettingsFileContentWithConfigs ¶ added in v0.18.6
func NewSettingsFileContentWithConfigs(dsl DSL, constraints map[string]string, subs []Substitution, extraConfigs []string) (string, error)
NewSettingsFileContentWithConfigs is NewSettingsFileContent plus extraConfigs: the names of configurations beyond the compile/runtime classpaths whose contents ship inside a packaged artifact and on which the pins must also be forced.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
content, err := gradlefile.NewSettingsFileContentWithConfigs(
gradlefile.Groovy,
map[string]string{"a.b:c": "1.0"},
nil,
[]string{"lineageImplementation"},
)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(strings.Contains(content, "configuration.name in ['lineageImplementation']"))
}
Output: true
func NormalizeAlias ¶
NormalizeAlias normalizes a catalog accessor path (netty.codec.http) to the catalog entry key form (netty-codec-http). Gradle generates accessors by splitting alias keys on '-', '_' and '.'; normalizing to dashes matches how keys are conventionally written in catalog files.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
fmt.Println(gradlefile.NormalizeAlias("netty.codec.http"))
}
Output: netty-codec-http
func ValidateCoordinate ¶
ValidateCoordinate reports whether a group or artifact identifier is safe to embed in a Gradle file.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
fmt.Println(gradlefile.ValidateCoordinate("io.netty"))
fmt.Println(gradlefile.ValidateCoordinate("io.netty'") != nil)
}
Output: <nil> true
func ValidateModule ¶ added in v0.18.0
ValidateModule reports whether module is a well-formed "group:artifact" coordinate safe to embed in a managed-block rule. Callers use it to decide whether a dependency can be force-pinned: aliases that are not real coordinates (e.g. Spring Boot's library("Commons Lang3") display names) fail this check and must not be added to the managed block.
func ValidateVersion ¶
ValidateVersion reports whether version is safe to embed in a Gradle file.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
fmt.Println(gradlefile.ValidateVersion("4.1.133.Final"))
fmt.Println(gradlefile.ValidateVersion(`1.0"; exec("rm")`) != nil)
}
Output: <nil> true
Types ¶
type BuildFile ¶
type BuildFile struct {
// contains filtered or unexported fields
}
BuildFile is a parsed Gradle build script.
func ParseBuild ¶
ParseBuild parses a Gradle build script (build.gradle, build.gradle.kts or any other *.gradle(.kts) script). The DSL dialect is derived from the path.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
content := []byte(`dependencies {
implementation "io.netty:netty-codec:4.1.100.Final"
implementation "ch.qos.logback:logback-classic:${logbackVersion}"
}`)
build, err := gradlefile.ParseBuild("build.gradle", content)
if err != nil {
fmt.Println(err)
return
}
for _, dep := range build.Dependencies() {
fmt.Printf("%s:%s version=%q varRef=%q\n", dep.Group, dep.Artifact, dep.Version, dep.VarRef)
}
}
Output: io.netty:netty-codec version="4.1.100.Final" varRef="" ch.qos.logback:logback-classic version="" varRef="logbackVersion"
func (*BuildFile) ChangeCount ¶
ChangeCount returns the number of queued edits that modify the content.
func (*BuildFile) Dependencies ¶
func (f *BuildFile) Dependencies() []DependencyDecl
Dependencies returns all dependency declarations found in the script.
func (*BuildFile) ForcedCoordinates ¶
ForcedCoordinates returns the "group:artifact" -> version entries of a legacy force block in this build file, or an empty map when none exists. Current omnibump writes the managed block to the settings script (see SettingsFile.EnsureManagedBlock); this reader keeps older build-script force blocks visible to the project model.
func (*BuildFile) ResolutionRules ¶
func (f *BuildFile) ResolutionRules() []ResolutionRule
ResolutionRules returns all dependency resolve rules found in the script.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
content := []byte(`eachDependency { DependencyResolveDetails details ->
if (details.requested.group == "io.netty" && !details.requested.name.startsWith("netty-tcnative-")) {
details.useVersion(libs.versions.netty.get())
}
if (details.requested.group == 'com.signalfx.public') {
if (details.requested.name == 'signalfx-java') {
details.useVersion '1.0.49'
}
}
}`)
build, _ := gradlefile.ParseBuild("build.gradle", content)
for _, rule := range build.ResolutionRules() {
fmt.Printf("group=%s artifact=%q catalogKey=%q version=%q\n", rule.Group, rule.Artifact, rule.CatalogKey, rule.Version)
}
// Literal rules are editable in place; catalog-backed rules are bumped
// through their [versions] key instead.
for _, rule := range build.ResolutionRules() {
if rule.Version != "" {
if err := build.SetResolutionRuleVersion(rule, "1.0.50"); err != nil {
fmt.Println(err)
}
}
}
fmt.Println("changed:", build.Changed())
}
Output: group=io.netty artifact="" catalogKey="netty" version="" group=com.signalfx.public artifact="signalfx-java" catalogKey="" version="1.0.49" changed: true
func (*BuildFile) SetDependencyVersion ¶
func (f *BuildFile) SetDependencyVersion(d DependencyDecl, version string) error
SetDependencyVersion queues an in-place rewrite of d's version literal. Declarations whose version is a variable reference cannot be edited here; update the variable definition instead.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
build, _ := gradlefile.ParseBuild("build.gradle", []byte(`implementation "io.netty:netty-codec:4.1.100.Final"`))
for _, dep := range build.Dependencies() {
if err := build.SetDependencyVersion(dep, "4.1.133.Final"); err != nil {
fmt.Println(err)
return
}
}
fmt.Println(string(build.Content()))
fmt.Println("changed:", build.Changed(), "edits:", build.ChangeCount())
}
Output: implementation "io.netty:netty-codec:4.1.133.Final" changed: true edits: 1
func (*BuildFile) SetResolutionRuleVersion ¶
func (f *BuildFile) SetResolutionRuleVersion(r ResolutionRule, version string) error
SetResolutionRuleVersion queues an in-place rewrite of r's version literal. Rules whose version comes from a catalog key or variable cannot be edited here; update the referenced source instead.
func (*BuildFile) SetVariable ¶
SetVariable queues an in-place rewrite of v's value.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
build, _ := gradlefile.ParseBuild("dependencies.gradle", []byte(`versions += [
log4j2: "2.25.1",
]`))
for _, variable := range build.Variables() {
if variable.Path() == "versions.log4j2" {
if err := build.SetVariable(variable, "2.25.4"); err != nil {
fmt.Println(err)
return
}
}
}
fmt.Println(string(build.Content()))
}
Output: versions += [ log4j2: "2.25.4", ]
func (*BuildFile) ShipConfigs ¶ added in v0.18.6
func (f *BuildFile) ShipConfigs() []ShipConfigRef
ShipConfigs returns the configuration references bundled into shipped artifacts by packaging tasks in this build script.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
// A shadowJar bundling a custom configuration alongside runtimeClasspath:
// both end up inside the fat jar, so both must be force-pinned.
content := []byte("shadowJar {\n configurations = [project.configurations.runtimeClasspath, project.configurations.lineageImplementation]\n}\n")
build, _ := gradlefile.ParseBuild("build.gradle", content)
for _, ref := range build.ShipConfigs() {
fmt.Println(ref.Name)
}
}
Output: runtimeClasspath lineageImplementation
type CatalogFile ¶
type CatalogFile struct {
// contains filtered or unexported fields
}
CatalogFile is a parsed gradle/libs.versions.toml version catalog. The TOML structure is read with a real TOML parser; edits are line-targeted splices on the raw text so formatting, comments and key alignment survive.
func ParseCatalog ¶
func ParseCatalog(path string, content []byte) (*CatalogFile, error)
ParseCatalog parses a libs.versions.toml version catalog.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
content := []byte(`[versions]
netty = "4.2.12.Final"
[libraries]
netty-codec = { module = "io.netty:netty-codec", version.ref = "netty" }
okio = { module = "com.squareup.okio:okio", version = "3.4.0" }
`)
catalog, err := gradlefile.ParseCatalog("gradle/libs.versions.toml", content)
if err != nil {
fmt.Println(err)
return
}
for _, library := range catalog.Libraries() {
fmt.Printf("%s -> ref=%q inline=%q\n", library.Module(), library.VersionRef, library.Version)
}
if err := catalog.SetVersion("netty", "4.2.13.Final"); err != nil {
fmt.Println(err)
return
}
for _, version := range catalog.Versions() {
fmt.Println(version.Key)
}
fmt.Println("changed:", catalog.Changed(), "edits:", catalog.ChangeCount(), catalog.Path())
}
Output: io.netty:netty-codec -> ref="netty" inline="" com.squareup.okio:okio -> ref="" inline="3.4.0" netty changed: true edits: 1 gradle/libs.versions.toml
func (*CatalogFile) ChangeCount ¶
func (f *CatalogFile) ChangeCount() int
ChangeCount returns the number of queued edits that modify the content.
func (*CatalogFile) Changed ¶
func (f *CatalogFile) Changed() bool
Changed reports whether any queued edit modifies the original content.
func (*CatalogFile) Content ¶
func (f *CatalogFile) Content() []byte
Content renders the catalog with all queued edits applied.
func (*CatalogFile) Libraries ¶
func (f *CatalogFile) Libraries() []CatalogLibrary
Libraries returns the [libraries] entries with resolvable coordinates.
func (*CatalogFile) Path ¶
func (f *CatalogFile) Path() string
Path returns the file path the catalog was parsed from.
func (*CatalogFile) SetLibraryVersion ¶
func (f *CatalogFile) SetLibraryVersion(lib CatalogLibrary, value string) error
SetLibraryVersion queues a rewrite of lib's inline version literal. Libraries that use version.ref are updated through SetVersion on the referenced key instead.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
catalog, _ := gradlefile.ParseCatalog("libs.versions.toml", []byte(`[libraries]
okio = { module = "com.squareup.okio:okio", version = "3.4.0" }
`))
for _, library := range catalog.Libraries() {
if err := catalog.SetLibraryVersion(library, "3.6.0"); err != nil {
fmt.Println(err)
return
}
}
fmt.Print(string(catalog.Content()))
}
Output: [libraries] okio = { module = "com.squareup.okio:okio", version = "3.6.0" }
func (*CatalogFile) SetVersion ¶
func (f *CatalogFile) SetVersion(key, value string) error
SetVersion queues a rewrite of the [versions] entry named key.
func (*CatalogFile) Versions ¶
func (f *CatalogFile) Versions() []CatalogVersion
Versions returns the [versions] entries with string values.
type CatalogLibrary ¶
type CatalogLibrary struct {
// Alias is the catalog entry key, e.g. "netty-codec".
Alias string
// Group and Artifact are the Maven coordinates.
Group string
Artifact string
// VersionRef is the referenced [versions] key, or empty.
VersionRef string
// Version is the inline version literal, or empty.
Version string
// contains filtered or unexported fields
}
CatalogLibrary is one library entry of a version catalog, mapping an alias to Maven coordinates and a version (either by reference or inline).
func (CatalogLibrary) Module ¶
func (l CatalogLibrary) Module() string
Module returns the library's "group:artifact" module coordinates.
type CatalogVersion ¶
type CatalogVersion struct {
// Key is the version key, e.g. "netty".
Key string
// Value is the current version string.
Value string
// contains filtered or unexported fields
}
CatalogVersion is one version entry of a version catalog: a [versions] key in a TOML catalog or a version("key", "value") declaration in a settings script's inline catalog.
type DSL ¶
type DSL int
DSL identifies the Gradle script dialect of a file.
func DSLFromPath ¶
DSLFromPath returns the DSL dialect implied by a file path.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
fmt.Println(gradlefile.DSLFromPath("build.gradle") == gradlefile.Groovy)
fmt.Println(gradlefile.DSLFromPath("build.gradle.kts") == gradlefile.Kotlin)
}
Output: true true
type DeclKind ¶
type DeclKind int
DeclKind identifies the syntactic form of a dependency declaration.
const ( // StringNotation is implementation("group:artifact:version") or the // paren-less Groovy form, including coordinate values in ext maps. StringNotation DeclKind = iota // MapNotationKotlin is group = "g", name = "a", version = "v". MapNotationKotlin // MapNotationGroovy is group: 'g', name: 'a', version: 'v'. MapNotationGroovy // LibraryFn is the Spring Boot bom-plugin form library("name", "version"). LibraryFn // StrictlyBlock is a rich-version constraint version { strictly("v") }. StrictlyBlock // CatalogRef is a version-catalog accessor such as api(libs.netty.codec); // it carries no version of its own. CatalogRef // DependencySet is one entry of a Spring dependency-management plugin // dependencySet(group: 'g', version: 'v') { entry 'a' } block. All // entries of a set share one version literal. DependencySet )
type DependencyDecl ¶
type DependencyDecl struct {
// Group and Artifact are the Maven coordinates. Group is empty for
// LibraryFn declarations (the library name is matched against artifact
// ids) and for CatalogRef/StrictlyBlock declarations identified only by a
// catalog alias.
Group string
Artifact string
// Version is the literal version, or empty when the version is a
// variable reference or the declaration carries no version.
Version string
// VarRef is the referenced variable path when the version is
// interpolated, e.g. "nettyVersion" or "versions.log4j2".
VarRef string
// CatalogAlias is the version-catalog accessor path (dots preserved,
// without the "libs." prefix) for CatalogRef and alias-based
// StrictlyBlock declarations.
CatalogAlias string
// Kind is the syntactic form of the declaration.
Kind DeclKind
// contains filtered or unexported fields
}
DependencyDecl is one dependency declaration found in a build script.
type PropertiesFile ¶
type PropertiesFile struct {
// contains filtered or unexported fields
}
PropertiesFile is a parsed gradle.properties or version.properties-style file. Order, comments and unrelated lines are preserved on edit.
func ParseProperties ¶
func ParseProperties(path string, content []byte) (*PropertiesFile, error)
ParseProperties parses a properties file.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
properties, err := gradlefile.ParseProperties("gradle.properties", []byte("nettyVersion=4.1.125.Final\njackson = 2.15.0\n"))
if err != nil {
fmt.Println(err)
return
}
fmt.Println(properties.Keys())
if err := properties.Set("nettyVersion", "4.1.133.Final"); err != nil {
fmt.Println(err)
return
}
value, ok := properties.Get("nettyVersion")
fmt.Println(value, ok, len(properties.Entries()))
fmt.Print(string(properties.Content()))
}
Output: [nettyVersion jackson] 4.1.125.Final true 2 nettyVersion=4.1.133.Final jackson = 2.15.0
func (*PropertiesFile) ChangeCount ¶
func (f *PropertiesFile) ChangeCount() int
ChangeCount returns the number of queued edits that modify the content.
func (*PropertiesFile) Changed ¶
func (f *PropertiesFile) Changed() bool
Changed reports whether any queued edit modifies the original content.
func (*PropertiesFile) Content ¶
func (f *PropertiesFile) Content() []byte
Content renders the file with all queued edits applied.
func (*PropertiesFile) Entries ¶
func (f *PropertiesFile) Entries() []PropertyEntry
Entries returns all key/value pairs in file order.
func (*PropertiesFile) Get ¶
func (f *PropertiesFile) Get(key string) (string, bool)
Get returns the value of key and whether it is defined.
func (*PropertiesFile) Keys ¶
func (f *PropertiesFile) Keys() []string
Keys returns all defined property names in file order.
func (*PropertiesFile) Path ¶
func (f *PropertiesFile) Path() string
Path returns the file path the properties were parsed from.
func (*PropertiesFile) Set ¶
func (f *PropertiesFile) Set(key, value string) error
Set queues an in-place rewrite of key's value. Only the value segment of the line is replaced; separator style and surrounding content are preserved. All occurrences of the key are updated.
type PropertyEntry ¶
type PropertyEntry struct {
// Key is the property name.
Key string
// Value is the current value.
Value string
// contains filtered or unexported fields
}
PropertyEntry is one key/value pair of a properties file.
type ResolutionRule ¶
type ResolutionRule struct {
// Group is the dependency group the rule matches.
Group string
// Artifact narrows the rule to one module; empty matches the whole group.
Artifact string
// CatalogKey is the referenced [versions] key (normalized) when the rule
// reads a catalog version accessor such as libs.versions.netty.get().
CatalogKey string
// VarRef is the referenced variable path when the rule interpolates one.
VarRef string
// Version is the literal version, or empty.
Version string
// contains filtered or unexported fields
}
ResolutionRule is a dependency resolve rule found in a build script: a conditional inside resolutionStrategy.eachDependency that redirects a group (or one module) to a version source, e.g.
if (details.requested.group == "io.netty" && !details.requested.name.startsWith("netty-tcnative-")) {
details.useVersion(libs.versions.netty.get())
}
Rules link modules to the catalog key, variable or literal that governs their version even when no [libraries] entry or interpolation does.
type SettingsFile ¶
type SettingsFile struct {
// contains filtered or unexported fields
}
SettingsFile is a parsed settings.gradle(.kts) script. Only the inline version-catalog declarations are modeled.
func ParseSettings ¶
func ParseSettings(path string, content []byte) (*SettingsFile, error)
ParseSettings parses a settings.gradle(.kts) script.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
content := []byte(`dependencyResolutionManagement {
versionCatalogs {
create("libs") {
version("netty", "4.1.100.Final")
library("netty-codec", "io.netty", "netty-codec").versionRef("netty")
}
}
}`)
settings, err := gradlefile.ParseSettings("settings.gradle.kts", content)
if err != nil {
fmt.Println(err)
return
}
for _, version := range settings.CatalogVersions() {
if err := settings.SetCatalogVersion(version, "4.1.133.Final"); err != nil {
fmt.Println(err)
return
}
}
fmt.Println(len(settings.CatalogLibraries()), settings.Changed(), settings.ChangeCount(), settings.Path())
}
Output: 1 true 1 settings.gradle.kts
func (*SettingsFile) CatalogLibraries ¶
func (f *SettingsFile) CatalogLibraries() []CatalogLibrary
CatalogLibraries returns the inline catalog library declarations that reference a version key.
func (*SettingsFile) CatalogVersions ¶
func (f *SettingsFile) CatalogVersions() []CatalogVersion
CatalogVersions returns the inline catalog version declarations.
func (*SettingsFile) ChangeCount ¶
func (f *SettingsFile) ChangeCount() int
ChangeCount returns the number of queued edits that modify the content.
func (*SettingsFile) Changed ¶
func (f *SettingsFile) Changed() bool
Changed reports whether any queued edit modifies the original content.
func (*SettingsFile) Content ¶
func (f *SettingsFile) Content() []byte
Content renders the script with all queued edits applied.
func (*SettingsFile) EnsureManagedBlock ¶ added in v0.18.0
func (f *SettingsFile) EnsureManagedBlock(constraints map[string]string, subs []Substitution) error
EnsureManagedBlock queues an edit that guarantees the settings file's managed block pins every constraint and applies every substitution. An existing block is merged (new versions/targets win, entries deduplicated and sorted); otherwise the block is appended. The operation is idempotent.
Example ¶
package main
import (
"fmt"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
settings, _ := gradlefile.ParseSettings("settings.gradle", []byte("rootProject.name = 'demo'\n"))
err := settings.EnsureManagedBlock(
map[string]string{"io.netty:netty-handler": "4.1.135.Final"},
[]gradlefile.Substitution{{OldModule: "org.lz4:lz4-java", NewModule: "at.yawk.lz4:lz4-java", Version: "1.10.1"}},
)
if err != nil {
fmt.Println(err)
return
}
// Re-parsing the result exposes the managed block's effective pins: each
// constraint, and each substitution's new module at its target version.
pinned, _ := gradlefile.ParseSettings("settings.gradle", settings.Content())
fmt.Println(pinned.ManagedCoordinates()["io.netty:netty-handler"])
fmt.Println(pinned.ManagedCoordinates()["at.yawk.lz4:lz4-java"])
}
Output: 4.1.135.Final 1.10.1
func (*SettingsFile) EnsureManagedBlockWithConfigs ¶ added in v0.18.6
func (f *SettingsFile) EnsureManagedBlockWithConfigs(constraints map[string]string, subs []Substitution, extraConfigs []string) error
EnsureManagedBlockWithConfigs is EnsureManagedBlock plus extraConfigs: the names of configurations beyond the compile/runtime classpaths whose resolved contents ship inside a packaged artifact (fat jar, capsule, war, ...), on which the pins must also be forced.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/chainguard-dev/omnibump/pkg/gradlefile"
)
func main() {
settings, _ := gradlefile.ParseSettings("settings.gradle", []byte("rootProject.name = 'demo'\n"))
// lineageImplementation is bundled into the artifact but is not a classpath,
// so it is added to the managed block's guard alongside the default match.
err := settings.EnsureManagedBlockWithConfigs(
map[string]string{"a.b:c": "1.0"},
nil,
[]string{"lineageImplementation"},
)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(strings.Contains(string(settings.Content()), "configuration.name in ['lineageImplementation']"))
}
Output: true
func (*SettingsFile) ManagedCoordinates ¶ added in v0.18.0
func (f *SettingsFile) ManagedCoordinates() map[string]string
ManagedCoordinates returns the effective "group:artifact" -> version pins of the file's managed block: each constraint, plus each substitution's new module at its target version. This lets the project model surface the settings-managed pins to dependency validation.
func (*SettingsFile) Path ¶
func (f *SettingsFile) Path() string
Path returns the file path the script was parsed from.
func (*SettingsFile) SetCatalogVersion ¶
func (f *SettingsFile) SetCatalogVersion(c CatalogVersion, value string) error
SetCatalogVersion queues an in-place rewrite of c's value.
type ShipConfigRef ¶ added in v0.18.6
type ShipConfigRef struct {
// Name is the resolved configuration name (e.g. "lineageImplementation"),
// or empty when the bundling site references a configuration in a form
// omnibump cannot resolve to a literal name.
Name string
// Source labels how the reference was found (e.g. "configurations =",
// "from", "classpath", "embedConfiguration"), for diagnostics.
Source string
// Raw is a trimmed source snippet, surfaced in warnings for unresolved
// references.
Raw string
// Resolved reports whether Name was extracted. False marks a bundling site
// whose configuration could not be statically determined, so the operator
// must pin it explicitly.
Resolved bool
}
ShipConfigRef is a reference to a Gradle configuration whose resolved contents are bundled into a shipped artifact: a fat/uber jar (shadow plugin or a hand-rolled Jar task), a capsule, a distribution, or a war. omnibump must force its managed version pins on these configurations too, because a configuration whose name is not a compile or runtime classpath escapes managedConfigurations yet still ends up inside the published artifact (e.g. nextflow's shadowJar bundles a custom 'lineageImplementation' configuration).
type Substitution ¶ added in v0.18.0
Substitution is a coordinate swap: every request for OldModule ("group:artifact") is redirected to NewModule ("group:artifact") at Version. It is the resolution-rule analog of a version bump for the case where the dependency's coordinate itself changes (e.g. a fork), and it applies to both declared and transitive requests.
type VarDef ¶
type VarDef struct {
// Name is the variable or map-entry name, e.g. "nettyVersion" or
// "log4j2".
Name string
// MapName is the enclosing Groovy map variable name (e.g. "versions")
// or empty for flat definitions.
MapName string
// Value is the current value.
Value string
// contains filtered or unexported fields
}
VarDef is one version-variable definition found in a build script: a flat ext property, a Kotlin extra property, or an entry in a Groovy version map.