Skip to content

Commit

Permalink
Merge pull request rmohr#80 from kellyma2/rpmtree
Browse files Browse the repository at this point in the history
Add support for generating lockfiles to rpmtree
  • Loading branch information
kellyma2 authored Jan 31, 2025
2 parents f8b077c + 6cd5c31 commit 3f9e62b
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 49 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,35 @@ the `--nobest` option can be supplied. With this option all packages are
considered. Newest packages will have the higest weight but it may not always be
able to choose them and older packages may be pulled in instead.

### Lock files

bazeldnf can use lock files as the source of RPMs in lieu of using the WORKSPACE file. These
can be hand written or generated with `bazeldnf rpmtree` similarly to how WORKSPACE files work.
Lock files can *only* be used when working in bzlmod mode, not in workspace mode.

To generate lock files you can run the following:

```bash
bazeldnf rpmtree --lockfile rpms.json --configname myrpms --name libvirttree libvirt
```

The lock file JSON format is as follows:
```
{
"name": "bazeldnf-rpms",
"rpms": [
{
"name": "libvirt-libs",
"sha256": "aac272a2ace134b5ef60a41e6624deb24331e79c76699ef6cef0dca22d94ac7e",
"urls": [
"https://kojipkgs.fedoraproject.org//packages/libvirt/11.0.0/1.fc42/x86_64/libvirt-libs-11.0.0-1.fc42.x86_64.rpm"
]
}
]
}
```

### Dependency resolution limitations

##### Missing features
Expand Down
163 changes: 125 additions & 38 deletions cmd/rpmtree.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (

"github.com/bazelbuild/buildtools/build"
"github.com/rmohr/bazeldnf/cmd/template"
"github.com/rmohr/bazeldnf/pkg/api"
"github.com/rmohr/bazeldnf/pkg/api/bazeldnf"
"github.com/rmohr/bazeldnf/pkg/bazel"
"github.com/rmohr/bazeldnf/pkg/reducer"
"github.com/rmohr/bazeldnf/pkg/repo"
Expand All @@ -21,22 +23,117 @@ type rpmtreeOpts struct {
workspace string
toMacro string
buildfile string
configname string
lockfile string
name string
public bool
forceIgnoreRegex []string
}

var rpmtreeopts = rpmtreeOpts{}

type Handler interface {
Process(pkgs []*api.Package, arch string, buildfile *build.File) error
Write() error
}

type MacroHandler struct {
bzl, defName string
bzlfile *build.File
}

func NewMacroHandler(toMacro string) (Handler, error) {
bzl, defName, err := bazel.ParseMacro(rpmtreeopts.toMacro)

if err != nil {
return nil, err
}

bzlfile, err := bazel.LoadBzl(bzl)
if err != nil {
return nil, err
}

return &MacroHandler{
bzl: bzl,
bzlfile: bzlfile,
defName: defName,
}, nil
}

func (h *MacroHandler) Process(pkgs []*api.Package, arch string, buildfile *build.File) error {
if err := bazel.AddBzlfileRPMs(h.bzlfile, h.defName, pkgs, arch); err != nil {
return err
}

bazel.PruneBzlfileRPMs(buildfile, h.bzlfile, h.defName)
return nil
}

func (h *MacroHandler) Write() error {
return bazel.WriteBzl(false, h.bzlfile, h.bzl)
}

type WorkspaceHandler struct {
workspace string
workspacefile *build.File
}

func NewWorkspaceHandler(workspace string) (Handler, error) {
workspacefile, err := bazel.LoadWorkspace(workspace)
if err != nil {
return nil, err
}

return &WorkspaceHandler{
workspace: workspace,
workspacefile: workspacefile,
}, nil
}

func (h *WorkspaceHandler) Process(pkgs []*api.Package, arch string, buildfile *build.File) error {
if err := bazel.AddWorkspaceRPMs(h.workspacefile, pkgs, arch); err != nil {
return err
}

bazel.PruneWorkspaceRPMs(buildfile, h.workspacefile)
return nil
}

func (h *WorkspaceHandler) Write() error {
return bazel.WriteWorkspace(false, h.workspacefile, h.workspace)
}

type LockFileHandler struct {
filename string
config *bazeldnf.Config
}

func NewLockFileHandler(configname, filename string) (Handler, error) {
return &LockFileHandler{
filename: filename,
config: &bazeldnf.Config{
Name: configname,
RPMs: []bazeldnf.RPM{},
},
}, nil
}

func (h *LockFileHandler) Process(pkgs []*api.Package, arch string, buildfile *build.File) error {
return bazel.AddConfigRPMs(h.config, pkgs, arch)
}

func (h *LockFileHandler) Write() error {
return bazel.WriteLockFile(h.config, h.filename)
}

func NewRpmTreeCmd() *cobra.Command {

rpmtreeCmd := &cobra.Command{
Use: "rpmtree",
Short: "Writes a rpmtree rule and its rpmdependencies to bazel files",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, required []string) error {
writeToMacro := rpmtreeopts.toMacro != ""

repos, err := repo.LoadRepoFiles(rpmtreeopts.repofiles)
if err != nil {
return err
Expand Down Expand Up @@ -68,54 +165,42 @@ func NewRpmTreeCmd() *cobra.Command {
if err != nil {
return err
}
workspace, err := bazel.LoadWorkspace(rpmtreeopts.workspace)

var handler Handler
var configname string

if rpmtreeopts.toMacro != "" {
handler, err = NewMacroHandler(rpmtreeopts.toMacro)
} else if rpmtreeopts.lockfile != "" {
configname = rpmtreeopts.configname
handler, err = NewLockFileHandler(
rpmtreeopts.configname,
rpmtreeopts.lockfile,
)
} else {
handler, err = NewWorkspaceHandler(rpmtreeopts.workspace)
}

if err != nil {
return err
}
var bzlfile *build.File
var bzl, defName string
if writeToMacro {
bzl, defName, err = bazel.ParseMacro(rpmtreeopts.toMacro)
if err != nil {
return err
}
bzlfile, err = bazel.LoadBzl(bzl)
if err != nil {
return err
}
}

build, err := bazel.LoadBuild(rpmtreeopts.buildfile)
if err != nil {
return err
}
if writeToMacro {
err = bazel.AddBzlfileRPMs(bzlfile, defName, install, rpmtreeopts.arch)
if err != nil {
return err
}
} else {
err = bazel.AddWorkspaceRPMs(workspace, install, rpmtreeopts.arch)
if err != nil {
return err
}
}
bazel.AddTree(rpmtreeopts.name, build, install, rpmtreeopts.arch, rpmtreeopts.public)
if writeToMacro {
bazel.PruneBzlfileRPMs(build, bzlfile, defName)
} else {
bazel.PruneWorkspaceRPMs(build, workspace)
bazel.AddTree(rpmtreeopts.name, configname, build, install, rpmtreeopts.arch, rpmtreeopts.public)

if err := handler.Process(install, rpmtreeopts.arch, build); err != nil {
return err
}

logrus.Info("Writing bazel files.")
err = bazel.WriteWorkspace(false, workspace, rpmtreeopts.workspace)
err = handler.Write()
if err != nil {
return err
}
if writeToMacro {
err = bazel.WriteBzl(false, bzlfile, bzl)
if err != nil {
return err
}
}

err = bazel.WriteBuild(false, build, rpmtreeopts.buildfile)
if err != nil {
return err
Expand All @@ -136,6 +221,8 @@ func NewRpmTreeCmd() *cobra.Command {
rpmtreeCmd.Flags().StringVarP(&rpmtreeopts.workspace, "workspace", "w", "WORKSPACE", "Bazel workspace file")
rpmtreeCmd.Flags().StringVarP(&rpmtreeopts.toMacro, "to-macro", "", "", "Tells bazeldnf to write the RPMs to a macro in the given bzl file instead of the WORKSPACE file. The expected format is: macroFile%defName")
rpmtreeCmd.Flags().StringVarP(&rpmtreeopts.buildfile, "buildfile", "b", "rpm/BUILD.bazel", "Build file for RPMs")
rpmtreeCmd.Flags().StringVar(&rpmtreeopts.configname, "configname", "rpms", "config name to use in lockfile")
rpmtreeCmd.Flags().StringVar(&rpmtreeopts.lockfile, "lockfile", "", "lockfile for RPMs")
rpmtreeCmd.Flags().StringVar(&rpmtreeopts.name, "name", "", "rpmtree rule name")
rpmtreeCmd.Flags().StringArrayVar(&rpmtreeopts.forceIgnoreRegex, "force-ignore-with-dependencies", []string{}, "Packages matching these regex patterns will not be installed. Allows force-removing unwanted dependencies. Be careful, this can lead to hidden missing dependencies.")
rpmtreeCmd.MarkFlagRequired("name")
Expand Down
5 changes: 4 additions & 1 deletion pkg/api/bazeldnf/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ load("@rules_go//go:def.bzl", "go_library")

go_library(
name = "bazeldnf",
srcs = ["repo.go"],
srcs = [
"config.go",
"repo.go",
],
importpath = "github.com/rmohr/bazeldnf/pkg/api/bazeldnf",
visibility = ["//visibility:public"],
)
12 changes: 12 additions & 0 deletions pkg/api/bazeldnf/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package bazeldnf

type RPM struct {
Name string `json:"name"`
SHA256 string `json:"sha256"`
URLs []string `json:"urls"`
}

type Config struct {
Name string `json:"name"`
RPMs []RPM `json:"rpms"`
}
1 change: 1 addition & 0 deletions pkg/bazel/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/api",
"//pkg/api/bazeldnf",
"@com_github_bazelbuild_buildtools//build:go_default_library",
"@com_github_bazelbuild_buildtools//edit:go_default_library",
],
Expand Down
Loading

0 comments on commit 3f9e62b

Please sign in to comment.