11package main
22
33import (
4+ "cmp"
45 "encoding/json"
56 "fmt"
67 "os"
8+ "regexp"
79
810 "slices"
911
@@ -14,6 +16,7 @@ import (
1416 "github.com/rmohr/bazeldnf/pkg/sat"
1517 "github.com/sirupsen/logrus"
1618 "github.com/spf13/cobra"
19+ "golang.org/x/exp/maps"
1720)
1821
1922type BzlmodOpts struct {
@@ -122,8 +125,12 @@ func DumpJSON(result ResolvedResult, targets []string, cmdline []string) ([]byte
122125 }
123126
124127 alreadyInstalled := make (map [string ]bool )
125- packageNames := keys (allPackages )
128+ packageNames := sortedKeys (allPackages )
126129 for _ , name := range packageNames {
130+ if _ , ignored := forceIgnored [name ]; ignored {
131+ continue
132+ }
133+
127134 requires := allPackages [name ].Dependencies
128135 deps , err := computeDependencies (requires , providers , forceIgnored )
129136 if err != nil {
@@ -150,9 +157,13 @@ func DumpJSON(result ResolvedResult, targets []string, cmdline []string) ([]byte
150157 sortedPackages = append (sortedPackages , allPackages [name ])
151158 }
152159
160+ ignoredPackages := sortedKeys (forceIgnored )
161+
162+ slices .Sort (ignoredPackages )
163+
153164 lockFile := BzlmodLockFile {
154165 CommandLineArguments : cmdline ,
155- ForceIgnored : keys ( forceIgnored ) ,
166+ ForceIgnored : ignoredPackages ,
156167 Packages : sortedPackages ,
157168 Repositories : make (map [string ][]string ),
158169 }
@@ -187,7 +198,128 @@ func computeDependencies(requires []string, providers map[string]string, ignored
187198 }
188199 deps [provider ] = true
189200 }
190- return keys (deps ), nil
201+ return sortedKeys (deps ), nil
202+ }
203+
204+ func shouldInclude (target string , ignoreRegex []string ) bool {
205+ for _ , rex := range ignoreRegex {
206+ if match , err := regexp .MatchString (rex , target ); err != nil {
207+ logrus .Errorf ("Failed to match package %s with regex '%v': %v" , target , rex , err )
208+ return false
209+ } else if match {
210+ logrus .Debugf ("will not include %s as it matched %s" , target , rex )
211+ return false
212+ }
213+ }
214+ logrus .Debugf ("including %s" , target )
215+ return true
216+ }
217+
218+ func exploreAllDependenciesToExclude (input * api.Package , allPackages map [string ]* api.Package , previouslyExplored map [string ]bool ) []* api.Package {
219+ alreadyExplored := make (map [string ]* api.Package , 0 )
220+ pending := []* api.Package {input }
221+
222+ for len (pending ) > 0 {
223+ current := pending [0 ]
224+ pending = pending [1 :]
225+
226+ if _ , explored := previouslyExplored [current .Name ]; explored {
227+ logrus .Debugf ("previously explored %s" , current .Name )
228+ continue
229+ }
230+
231+ if _ , explored := alreadyExplored [current .Name ]; explored {
232+ continue
233+ }
234+
235+ alreadyExplored [current .Name ] = current
236+
237+ for _ , entry := range current .Format .Requires .Entries {
238+ pending = append (pending , allPackages [entry .Name ])
239+ }
240+ }
241+
242+ output := maps .Values (alreadyExplored )
243+ slices .SortStableFunc (output , func (a , b * api.Package ) int {
244+ return cmp .Compare (a .Name , b .Name )
245+ })
246+
247+ return output
248+ }
249+
250+ func filterIgnores (rpmsRequested []string , allAvailable []* api.Package , ignoreRegex []string ) ([]* api.Package , []* api.Package ) {
251+ /*
252+ * Given a list of rpmsRequested and a list of ignoreRegex then go through all the resolved rpms
253+ * in allAvailable to install and filter only those needed.
254+ */
255+ if len (ignoreRegex ) == 0 {
256+ return allAvailable , []* api.Package {}
257+ }
258+
259+ allAvailablePerName := make (map [string ]* api.Package , 0 )
260+
261+ for _ , rpm := range allAvailable {
262+ allAvailablePerName [rpm .Name ] = rpm
263+
264+ for _ , entry := range rpm .Format .Provides .Entries {
265+ allAvailablePerName [entry .Name ] = rpm
266+ }
267+
268+ for _ , entry := range rpm .Format .Files {
269+ allAvailablePerName [entry .Text ] = rpm
270+ }
271+ }
272+
273+ toInstall := make ([]* api.Package , 0 )
274+ ignored := make (map [string ]* api.Package , 0 )
275+
276+ explored := make (map [string ]bool , 0 )
277+ for _ , rpm := range rpmsRequested {
278+ target , ok := allAvailablePerName [rpm ]
279+ if ! ok {
280+ logrus .Errorf ("failed to match %s" , rpm )
281+ continue
282+ }
283+
284+ pending := []* api.Package {target }
285+ for len (pending ) > 0 {
286+ current := pending [0 ]
287+ logrus .Debugf ("processing %s" , current .Name )
288+ pending = pending [1 :]
289+ if _ , alreadyExplored := explored [current .Name ]; alreadyExplored {
290+ logrus .Debugf ("already iterated" )
291+ continue
292+ }
293+
294+ if ! shouldInclude (current .Name , ignoreRegex ) {
295+ toIgnore := exploreAllDependenciesToExclude (current , allAvailablePerName , explored )
296+ for _ , d := range toIgnore {
297+ logrus .Debugf ("excluding %s" , d .Name )
298+ ignored [d .Name ] = d
299+ explored [d .Name ] = true
300+ }
301+ continue
302+ }
303+
304+ explored [current .Name ] = true
305+
306+ toInstall = append (toInstall , current )
307+ for _ , dep := range current .Format .Requires .Entries {
308+ logrus .Debugf ("finding dependency provider for %s" , dep .Name )
309+ p , ok := allAvailablePerName [dep .Name ]
310+ if ok {
311+ pending = append (pending , p )
312+ }
313+ }
314+ }
315+ }
316+
317+ ignoredPackages := maps .Values (ignored )
318+ slices .SortStableFunc (ignoredPackages , func (a , b * api.Package ) int {
319+ return cmp .Compare (a .Name , b .Name )
320+ })
321+
322+ return toInstall , ignoredPackages
191323}
192324
193325func (opts * BzlmodOpts ) RunE (cmd * cobra.Command , rpms []string ) error {
@@ -214,7 +346,7 @@ func (opts *BzlmodOpts) RunE(cmd *cobra.Command, rpms []string) error {
214346
215347 solver := sat .NewResolver (resolvehelperopts .nobest )
216348 logrus .Info ("Loading involved packages into the rpmtreer." )
217- err = solver .LoadInvolvedPackages (involved , resolvehelperopts . forceIgnoreRegex , resolvehelperopts .onlyAllowRegex )
349+ err = solver .LoadInvolvedPackages (involved , [] string {} , resolvehelperopts .onlyAllowRegex )
218350 if err != nil {
219351 return err
220352 }
@@ -226,15 +358,19 @@ func (opts *BzlmodOpts) RunE(cmd *cobra.Command, rpms []string) error {
226358 }
227359
228360 logrus .Info ("Solving." )
229- install , _ , forceIgnored , err := solver .Resolve ()
361+ install , _ , _ , err := solver .Resolve ()
230362 if err != nil {
231363 return err
232364 }
233365
234366 logrus .Debugf ("install: %v" , install )
367+
368+ actualInstall , forceIgnored := filterIgnores (rpms , install , resolvehelperopts .forceIgnoreRegex )
369+
370+ logrus .Debugf ("actualInstall: %v" , actualInstall )
235371 logrus .Debugf ("forceIgnored: %v" , forceIgnored )
236372
237- result := ResolvedResult {Install : install , ForceIgnored : forceIgnored }
373+ result := ResolvedResult {Install : actualInstall , ForceIgnored : forceIgnored }
238374
239375 data , err := DumpJSON (result , rpms , os .Args [2 :])
240376
0 commit comments