github.com/kastenhq/syft@v0.0.0-20230821225854-0710af25cdbe/cmd/syft/cli/convert/convert.go (about)

     1  package convert
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  
     9  	"github.com/wagoodman/go-partybus"
    10  
    11  	"github.com/anchore/stereoscope"
    12  	"github.com/kastenhq/syft/cmd/syft/cli/eventloop"
    13  	"github.com/kastenhq/syft/cmd/syft/cli/options"
    14  	"github.com/kastenhq/syft/cmd/syft/internal/ui"
    15  	"github.com/kastenhq/syft/internal/bus"
    16  	"github.com/kastenhq/syft/internal/config"
    17  	"github.com/kastenhq/syft/internal/log"
    18  	"github.com/kastenhq/syft/syft"
    19  	"github.com/kastenhq/syft/syft/formats"
    20  	"github.com/kastenhq/syft/syft/sbom"
    21  )
    22  
    23  func Run(_ context.Context, app *config.Application, args []string) error {
    24  	log.Warn("convert is an experimental feature, run `syft convert -h` for help")
    25  
    26  	writer, err := options.MakeSBOMWriter(app.Outputs, app.File, app.OutputTemplatePath)
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	// could be an image or a directory, with or without a scheme
    32  	userInput := args[0]
    33  
    34  	var reader io.ReadCloser
    35  
    36  	if userInput == "-" {
    37  		reader = os.Stdin
    38  	} else {
    39  		f, err := os.Open(userInput)
    40  		if err != nil {
    41  			return fmt.Errorf("failed to open SBOM file: %w", err)
    42  		}
    43  		defer func() {
    44  			_ = f.Close()
    45  		}()
    46  		reader = f
    47  	}
    48  
    49  	eventBus := partybus.NewBus()
    50  	stereoscope.SetBus(eventBus)
    51  	syft.SetBus(eventBus)
    52  	subscription := eventBus.Subscribe()
    53  
    54  	return eventloop.EventLoop(
    55  		execWorker(reader, writer),
    56  		eventloop.SetupSignals(),
    57  		subscription,
    58  		stereoscope.Cleanup,
    59  		ui.Select(options.IsVerbose(app), app.Quiet)...,
    60  	)
    61  }
    62  
    63  func execWorker(reader io.Reader, writer sbom.Writer) <-chan error {
    64  	errs := make(chan error)
    65  	go func() {
    66  		defer close(errs)
    67  		defer bus.Exit()
    68  
    69  		s, _, err := formats.Decode(reader)
    70  		if err != nil {
    71  			errs <- fmt.Errorf("failed to decode SBOM: %w", err)
    72  			return
    73  		}
    74  
    75  		if s == nil {
    76  			errs <- fmt.Errorf("no SBOM produced")
    77  			return
    78  		}
    79  
    80  		if err := writer.Write(*s); err != nil {
    81  			errs <- fmt.Errorf("failed to write SBOM: %w", err)
    82  		}
    83  	}()
    84  	return errs
    85  }