@@ -5,12 +5,26 @@ import (
55 "fmt"
66 "log"
77 "os"
8+ "strings"
89
910 "github.com/supabase/postgres/nix/packages/sbom/internal/merge"
1011 "github.com/supabase/postgres/nix/packages/sbom/internal/nix"
12+ "github.com/supabase/postgres/nix/packages/sbom/internal/spdx"
1113 "github.com/supabase/postgres/nix/packages/sbom/internal/ubuntu"
1214)
1315
16+ // stringSliceFlag allows multiple values for a single flag
17+ type stringSliceFlag []string
18+
19+ func (s * stringSliceFlag ) String () string {
20+ return strings .Join (* s , ", " )
21+ }
22+
23+ func (s * stringSliceFlag ) Set (value string ) error {
24+ * s = append (* s , value )
25+ return nil
26+ }
27+
1428func main () {
1529 if len (os .Args ) < 2 {
1630 printUsage ()
@@ -91,12 +105,12 @@ func nixCommand(args []string) {
91105 outputFile := fs .String ("output" , "nix-sbom.spdx.json" , "Output file path" )
92106
93107 fs .Usage = func () {
94- fmt .Println ("Usage: sbom nix <derivation-path> [flags]" )
108+ fmt .Println ("Usage: sbom nix <derivation-path> [derivation-path...] [ flags]" )
95109 fmt .Println ()
96110 fmt .Println ("Generate Nix-only SBOM using sbomnix" )
97111 fmt .Println ()
98112 fmt .Println ("Arguments:" )
99- fmt .Println (" derivation-path Path to the Nix derivation ( required)" )
113+ fmt .Println (" derivation-path Path(s) to Nix derivation(s) (at least one required)" )
100114 fmt .Println ()
101115 fmt .Println ("Flags:" )
102116 fs .PrintDefaults ()
@@ -107,34 +121,43 @@ func nixCommand(args []string) {
107121 }
108122
109123 if fs .NArg () < 1 {
110- fmt .Println ("Error: derivation path required" )
124+ fmt .Println ("Error: at least one derivation path required" )
111125 fmt .Println ()
112126 fs .Usage ()
113127 os .Exit (1 )
114128 }
115129
116- derivationPath := fs .Arg (0 )
117-
118130 // Use sbomnix from PATH
119131 wrapper := nix .NewWrapper ("sbomnix" )
120132
121- if err := wrapper .Generate (derivationPath , * outputFile ); err != nil {
122- log .Fatalf ("Failed to generate Nix SBOM: %v" , err )
133+ if fs .NArg () == 1 {
134+ // Single path - use original method
135+ if err := wrapper .Generate (fs .Arg (0 ), * outputFile ); err != nil {
136+ log .Fatalf ("Failed to generate Nix SBOM: %v" , err )
137+ }
138+ } else {
139+ // Multiple paths - use new method
140+ paths := fs .Args ()
141+ if err := wrapper .GenerateMultiple (paths , * outputFile ); err != nil {
142+ log .Fatalf ("Failed to generate Nix SBOM: %v" , err )
143+ }
123144 }
124145
125146 fmt .Printf ("Nix SBOM generated successfully: %s\n " , * outputFile )
126147}
127148
128149func combinedCommand (args []string ) {
129150 fs := flag .NewFlagSet ("combined" , flag .ExitOnError )
130- nixTarget := fs .String ("nix-target" , "" , "Path to Nix derivation (required)" )
151+ var nixTargets stringSliceFlag
152+ fs .Var (& nixTargets , "nix-target" , "Path to Nix derivation (can be specified multiple times)" )
131153 outputFile := fs .String ("output" , "merged-sbom.spdx.json" , "Output file path" )
132154 includeFiles := fs .Bool ("include-files" , false , "Include file checksums for Ubuntu packages" )
133155 progress := fs .Bool ("progress" , true , "Show progress indicators" )
134156 noProgress := fs .Bool ("no-progress" , false , "Disable progress indicators" )
157+ nixOnly := fs .Bool ("nix-only" , false , "Generate Nix-only SBOM (skip Ubuntu packages)" )
135158
136159 fs .Usage = func () {
137- fmt .Println ("Usage: sbom combined --nix-target <derivation> [flags]" )
160+ fmt .Println ("Usage: sbom combined --nix-target <derivation> [--nix-target <derivation>...] [ flags]" )
138161 fmt .Println ()
139162 fmt .Println ("Generate and merge both Ubuntu and Nix SBOMs" )
140163 fmt .Println ()
@@ -146,8 +169,8 @@ func combinedCommand(args []string) {
146169 os .Exit (1 )
147170 }
148171
149- if * nixTarget == "" {
150- fmt .Println ("Error: --nix-target is required" )
172+ if len ( nixTargets ) == 0 {
173+ fmt .Println ("Error: at least one --nix-target is required" )
151174 fmt .Println ()
152175 fs .Usage ()
153176 os .Exit (1 )
@@ -162,33 +185,52 @@ func combinedCommand(args []string) {
162185 }
163186 defer os .RemoveAll (tmpDir )
164187
165- ubuntuSBOM := fmt . Sprintf ( "%s/ubuntu-sbom.spdx.json" , tmpDir )
166- nixSBOM := fmt . Sprintf ( "%s/nix-sbom.spdx.json" , tmpDir )
188+ merger := merge . NewMerger ( )
189+ nixWrapper := nix . NewWrapper ( "sbomnix" )
167190
168- // Generate Ubuntu SBOM
169- fmt .Println ("Generating Ubuntu SBOM..." )
170- ubuntuGen := ubuntu .NewGenerator (* includeFiles , showProgress )
171- ubuntuDoc , err := ubuntuGen .Generate ()
172- if err != nil {
173- log .Fatalf ("Failed to generate Ubuntu SBOM: %v" , err )
174- }
175- if err := ubuntuGen .Save (ubuntuDoc , ubuntuSBOM ); err != nil {
176- log .Fatalf ("Failed to save Ubuntu SBOM: %v" , err )
177- }
191+ var ubuntuSBOM string
192+ if ! * nixOnly {
193+ // Generate Ubuntu SBOM
194+ fmt .Println ("Generating Ubuntu SBOM..." )
195+ ubuntuSBOM = fmt .Sprintf ("%s/ubuntu-sbom.spdx.json" , tmpDir )
196+ ubuntuGen := ubuntu .NewGenerator (* includeFiles , showProgress )
197+ ubuntuDoc , err := ubuntuGen .Generate ()
198+ if err != nil {
199+ log .Fatalf ("Failed to generate Ubuntu SBOM: %v" , err )
200+ }
201+ if err := ubuntuGen .Save (ubuntuDoc , ubuntuSBOM ); err != nil {
202+ log .Fatalf ("Failed to save Ubuntu SBOM: %v" , err )
203+ }
204+ }
205+
206+ // Generate Nix SBOM(s)
207+ fmt .Printf ("Generating Nix SBOM from %d target(s)...\n " , len (nixTargets ))
208+ nixSBOM := fmt .Sprintf ("%s/nix-sbom.spdx.json" , tmpDir )
178209
179- // Generate Nix SBOM
180- fmt .Println ("Generating Nix SBOM..." )
181- nixWrapper := nix .NewWrapper ("sbomnix" )
182- if err := nixWrapper .Generate (* nixTarget , nixSBOM ); err != nil {
183- log .Fatalf ("Failed to generate Nix SBOM: %v" , err )
210+ if len (nixTargets ) == 1 {
211+ if err := nixWrapper .Generate (nixTargets [0 ], nixSBOM ); err != nil {
212+ log .Fatalf ("Failed to generate Nix SBOM: %v" , err )
213+ }
214+ } else {
215+ if err := nixWrapper .GenerateMultiple ([]string (nixTargets ), nixSBOM ); err != nil {
216+ log .Fatalf ("Failed to generate Nix SBOM: %v" , err )
217+ }
184218 }
185219
186220 // Merge SBOMs
187221 fmt .Println ("Merging SBOMs..." )
188- merger := merge .NewMerger ()
189- mergedDoc , err := merger .Merge (ubuntuSBOM , nixSBOM )
190- if err != nil {
191- log .Fatalf ("Failed to merge SBOMs: %v" , err )
222+ var mergedDoc * spdx.Document
223+ if * nixOnly {
224+ // Load and output Nix SBOM directly
225+ mergedDoc , err = merger .LoadDocument (nixSBOM )
226+ if err != nil {
227+ log .Fatalf ("Failed to load Nix SBOM: %v" , err )
228+ }
229+ } else {
230+ mergedDoc , err = merger .Merge (ubuntuSBOM , nixSBOM )
231+ if err != nil {
232+ log .Fatalf ("Failed to merge SBOMs: %v" , err )
233+ }
192234 }
193235
194236 if err := merger .Save (mergedDoc , * outputFile ); err != nil {
0 commit comments