Skip to content

Commit 113430c

Browse files
Merge pull request #101 from kellyma2/lockfile
Add lockfile command to bazeldnf
2 parents 0523988 + c30481b commit 113430c

File tree

8 files changed

+655
-9
lines changed

8 files changed

+655
-9
lines changed

cmd/BUILD.bazel

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
load("@rules_go//go:def.bzl", "go_binary", "go_library")
1+
load("@rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
22
load("//bazeldnf:toolchain.bzl", "bazeldnf_toolchain")
33

44
go_library(
55
name = "cmd_lib",
66
srcs = [
77
"bazeldnf.go",
8+
"config_helper.go",
89
"fetch.go",
910
"filter.go",
1011
"init.go",
1112
"ldd.go",
13+
"lockfile.go",
1214
"prune.go",
1315
"reduce.go",
1416
"resolve.go",
@@ -40,6 +42,7 @@ go_library(
4042
"@com_github_sirupsen_logrus//:logrus",
4143
"@com_github_spf13_cobra//:cobra",
4244
"@org_golang_x_crypto//openpgp",
45+
"@org_golang_x_exp//maps",
4346
],
4447
)
4548

@@ -60,3 +63,14 @@ toolchain(
6063
toolchain = ":host-toolchain",
6164
toolchain_type = "//bazeldnf:toolchain_type",
6265
)
66+
67+
go_test(
68+
name = "cmd_test",
69+
srcs = ["config_helper_test.go"],
70+
embed = [":cmd_lib"],
71+
deps = [
72+
"//pkg/api",
73+
"//pkg/api/bazeldnf",
74+
"@com_github_onsi_gomega//:gomega",
75+
],
76+
)

cmd/config_helper.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package main
2+
3+
import (
4+
"cmp"
5+
"fmt"
6+
"slices"
7+
8+
"github.com/rmohr/bazeldnf/pkg/api"
9+
"github.com/rmohr/bazeldnf/pkg/api/bazeldnf"
10+
"github.com/sirupsen/logrus"
11+
"golang.org/x/exp/maps"
12+
)
13+
14+
func keys[K cmp.Ordered, V any](m map[K]V) []K {
15+
keys := maps.Keys(m)
16+
slices.Sort(keys)
17+
return keys
18+
}
19+
20+
func toConfig(install, forceIgnored []*api.Package, targets []string, cmdline []string) (*bazeldnf.Config, error) {
21+
ignored := make(map[string]bool)
22+
for _, forceIgnoredPackage := range forceIgnored {
23+
ignored[forceIgnoredPackage.Name] = true
24+
}
25+
26+
allPackages := make(map[string]*bazeldnf.RPM)
27+
repositories := make(map[string][]string)
28+
for _, installPackage := range install {
29+
repositories[installPackage.Repository.Name] = installPackage.Repository.Mirrors
30+
31+
deps := make([]string, 0, len(installPackage.Format.Requires.Entries))
32+
for _, entry := range installPackage.Format.Requires.Entries {
33+
deps = append(deps, entry.Name)
34+
}
35+
36+
slices.Sort(deps)
37+
38+
allPackages[installPackage.Name] = &bazeldnf.RPM{
39+
Name: installPackage.Name,
40+
SHA256: installPackage.Checksum.Text,
41+
URLs: []string{installPackage.Location.Href},
42+
Repository: installPackage.Repository.Name,
43+
Dependencies: deps,
44+
}
45+
}
46+
47+
providers := collectProviders(forceIgnored, install)
48+
packageNames := keys(allPackages)
49+
sortedPackages := make([]*bazeldnf.RPM, 0, len(packageNames))
50+
for _, name := range packageNames {
51+
pkg := allPackages[name]
52+
deps, err := collectDependencies(name, pkg.Dependencies, providers, ignored)
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
pkg.SetDependencies(deps)
58+
59+
sortedPackages = append(sortedPackages, pkg)
60+
}
61+
62+
lockFile := bazeldnf.Config{
63+
CommandLineArguments: cmdline,
64+
ForceIgnored: keys(ignored),
65+
RPMs: sortedPackages,
66+
Repositories: repositories,
67+
Targets: targets,
68+
}
69+
70+
return &lockFile, nil
71+
}
72+
73+
func collectProviders(pkgSets ...[]*api.Package) map[string]string {
74+
providers := map[string]string{}
75+
for _, pkgSet := range pkgSets {
76+
for _, pkg := range pkgSet {
77+
for _, entry := range pkg.Format.Provides.Entries {
78+
providers[entry.Name] = pkg.Name
79+
}
80+
81+
for _, entry := range pkg.Format.Files {
82+
providers[entry.Text] = pkg.Name
83+
}
84+
}
85+
}
86+
87+
return providers
88+
}
89+
90+
func collectDependencies(pkg string, requires []string, providers map[string]string, ignored map[string]bool) ([]string, error) {
91+
depSet := make(map[string]bool)
92+
for _, req := range requires {
93+
if ignored[req] {
94+
logrus.Debugf("Ignoring dependency %s", req)
95+
continue
96+
}
97+
logrus.Debugf("Resolving dependency %s", req)
98+
provider, ok := providers[req]
99+
if !ok {
100+
return nil, fmt.Errorf("could not find provider for %s", req)
101+
}
102+
logrus.Debugf("Found provider %s for %s", provider, req)
103+
if ignored[provider] {
104+
logrus.Debugf("Ignoring provider %s for %s", provider, req)
105+
continue
106+
}
107+
depSet[provider] = true
108+
}
109+
110+
deps := keys(depSet)
111+
112+
found := map[string]bool{pkg: true}
113+
114+
// RPMs may have circular dependencies, even depend on themselves.
115+
// we need to ignore such dependencies
116+
nonCyclicDeps := make([]string, 0, len(deps))
117+
for _, dep := range deps {
118+
if found[dep] {
119+
continue
120+
}
121+
122+
nonCyclicDeps = append(nonCyclicDeps, dep)
123+
}
124+
125+
return nonCyclicDeps, nil
126+
}

0 commit comments

Comments
 (0)