1919# Copyright (c) OWASP Foundation. All Rights Reserved.
2020
2121import argparse
22+ import enum
2223import os
2324import sys
2425from datetime import datetime
2526from typing import Optional
2627
2728from cyclonedx .model import Tool
2829from cyclonedx .model .bom import Bom
29- from cyclonedx .output import BaseOutput , OutputFormat , SchemaVersion , get_instance
30+ from cyclonedx .output import BaseOutput , OutputFormat , SchemaVersion , get_instance as get_output_instance
3031from cyclonedx .parser import BaseParser
3132
3233from .parser .conda import CondaListExplicitParser , CondaListJsonParser
@@ -44,6 +45,22 @@ class CycloneDxCmdNoInputFileSupplied(CycloneDxCmdException):
4445 pass
4546
4647
48+ @enum .unique
49+ class _CLI_OUTPUT_FORMAT (enum .Enum ):
50+ XML = 'xml'
51+ JSON = 'json'
52+
53+
54+ _output_formats = {
55+ _CLI_OUTPUT_FORMAT .XML : OutputFormat .XML ,
56+ _CLI_OUTPUT_FORMAT .JSON : OutputFormat .JSON ,
57+ }
58+ _output_default_filenames = {
59+ _CLI_OUTPUT_FORMAT .XML : 'cyclonedx.xml' ,
60+ _CLI_OUTPUT_FORMAT .JSON : 'cyclonedx.json' ,
61+ }
62+
63+
4764class CycloneDxCmd :
4865 # Whether debug output is enabled
4966 _DEBUG_ENABLED : bool = False
@@ -59,6 +76,9 @@ def __init__(self, args: argparse.Namespace) -> None:
5976 self ._debug_message ('!!! DEBUG MODE ENABLED !!!' )
6077 self ._debug_message ('Parsed Arguments: {}' .format (self ._arguments ))
6178
79+ def _get_output_format (self ) -> _CLI_OUTPUT_FORMAT :
80+ return _CLI_OUTPUT_FORMAT (str (self ._arguments .output_format ).lower ())
81+
6282 def get_output (self ) -> BaseOutput :
6383 try :
6484 parser = self ._get_input_parser ()
@@ -94,17 +114,20 @@ def get_output(self) -> BaseOutput:
94114 vendor = 'CycloneDX' , name = 'cyclonedx-bom' , version = md_version ('cyclonedx-bom' )
95115 ))
96116
97- return get_instance (
117+ return get_output_instance (
98118 bom = bom ,
99- output_format = OutputFormat [ str ( self ._arguments . output_format ). upper ()],
119+ output_format = _output_formats [ self ._get_output_format ()],
100120 schema_version = SchemaVersion ['V{}' .format (
101121 str (self ._arguments .output_schema_version ).replace ('.' , '_' )
102122 )]
103123 )
104124
105125 def execute (self ) -> None :
126+ output_format = self ._get_output_format ()
127+ self ._debug_message (f'output_format: { output_format } ' )
128+
106129 # Quick check for JSON && SchemaVersion <= 1.1
107- if str ( self . _arguments . output_format ). upper () == ' JSON' and \
130+ if output_format == OutputFormat . JSON and \
108131 str (self ._arguments .output_schema_version ) in ['1.0' , '1.1' ]:
109132 self ._error_and_exit (
110133 message = 'CycloneDX schema does not support JSON output in Schema Versions < 1.2' ,
@@ -118,7 +141,9 @@ def execute(self) -> None:
118141 return
119142
120143 # Check directory writable
121- output_filename = os .path .realpath (self ._arguments .output_file )
144+ output_file = self ._arguments .output_file
145+ output_filename = os .path .realpath (
146+ output_file if isinstance (output_file , str ) else _output_default_filenames [output_format ])
122147 self ._debug_message ('Will be outputting SBOM to file at: {}' .format (output_filename ))
123148 output .output_to_file (filename = output_filename , allow_overwrite = self ._arguments .output_file_overwrite )
124149
@@ -177,7 +202,8 @@ def get_arg_parser(*, prog: Optional[str] = None) -> argparse.ArgumentParser:
177202 description = 'Choose the output format and schema version'
178203 )
179204 output_group .add_argument (
180- '--format' , action = 'store' , choices = ['json' , 'xml' ], default = 'xml' ,
205+ '--format' , action = 'store' ,
206+ choices = [f .value for f in _CLI_OUTPUT_FORMAT ], default = _CLI_OUTPUT_FORMAT .XML .value ,
181207 help = 'The output format for your SBOM (default: %(default)s)' ,
182208 dest = 'output_format'
183209 )
@@ -187,7 +213,8 @@ def get_arg_parser(*, prog: Optional[str] = None) -> argparse.ArgumentParser:
187213 dest = 'output_schema_version'
188214 )
189215 output_group .add_argument (
190- '-o' , '--o' , '--output' , action = 'store' , metavar = 'FILE_PATH' , default = 'cyclonedx.xml' , required = False ,
216+ # string, None or True. True=autodetect(based-on-format)
217+ '-o' , '--o' , '--output' , action = 'store' , metavar = 'FILE_PATH' , default = True , required = False ,
191218 help = 'Output file path for your SBOM (set to \' -\' to output to STDOUT)' , dest = 'output_file'
192219 )
193220 output_group .add_argument (
0 commit comments