Skip to content

Commit c0f0766

Browse files
authored
Merge pull request #257 from CycloneDX/fix/256-no-default-file-when-no-input-on-stdin
FIX: Fallback to default manifest names in current directory when no `-i` supplied and nothing piped in via STDIN
2 parents 6924dac + 47612e6 commit c0f0766

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,26 @@ You can then run `cyclonedx-bom` as follows:
135135
cyclonedx-bom -p -i PATH/TO/poetry.lock -o sbom.xml
136136
```
137137

138-
#### Pip / Requirements
138+
If your `poetry.lock` is in the current working directory, you can also shorten this to:
139+
```
140+
cyclonedx-bom -p -o sbom.xml
141+
```
142+
143+
#### Pip
144+
145+
We currently support `Pipfile.lock` manifest files.
146+
147+
You can then run `cyclonedx-bom` as follows:
148+
```
149+
cyclonedx-bom -pip -i PATH/TO/Pipfile.lock -o sbom.xml
150+
```
151+
152+
If your `Pipfile.lock` is in the current working directory, you can also shorten this to:
153+
```
154+
cyclonedx-bom -pip -o sbom.xml
155+
```
156+
157+
#### Requirements
139158

140159
We currently support `requirements.txt` manifest files. Note that a BOM such as CycloneDX expects exact version numbers,
141160
therefore if you wish to generate a BOM from a `requirements.txt`, these must be frozen. This can be accomplished via:
@@ -144,11 +163,16 @@ therefore if you wish to generate a BOM from a `requirements.txt`, these must be
144163
pip freeze > requirements.txt
145164
```
146165

147-
You can then run `cyclonedx-py` as follows:
166+
You can then run `cyclonedx-bom` as follows:
148167
```
149168
cyclonedx-bom -r -i PATH/TO/requirements.txt -o sbom.xml
150169
```
151170

171+
If your `requirements.txt` is in the current working directory, you can also shorten this to:
172+
```
173+
cyclonedx-bom -r -o sbom.xml
174+
```
175+
152176
This will generate a CycloneDX and output to STDOUT in XML using the latest schema version `1.3` by default.
153177

154178
**Note:** If you failed to freeze your dependencies before passing the `requirements.txt` data to `cyclonedx-bom`,

cyclonedx_py/client.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@
3333
from cyclonedx.parser.requirements import RequirementsParser
3434

3535

36+
class CycloneDxCmdException(Exception):
37+
pass
38+
39+
40+
class CycloneDxCmdNoInputFileSupplied(CycloneDxCmdException):
41+
pass
42+
43+
3644
class CycloneDxCmd:
3745
# Whether debug output is enabled
3846
_DEBUG_ENABLED: bool = False
@@ -49,7 +57,14 @@ def __init__(self, args: argparse.Namespace):
4957
self._debug_message('Parsed Arguments: {}'.format(self._arguments))
5058

5159
def get_output(self) -> BaseOutput:
52-
parser = self._get_input_parser()
60+
try:
61+
parser = self._get_input_parser()
62+
except CycloneDxCmdNoInputFileSupplied as e:
63+
print(f'ERROR: {str(e)}')
64+
exit(1)
65+
except CycloneDxCmdException as e:
66+
print(f'ERROR: {str(e)}')
67+
exit(1)
5368

5469
if parser.has_warnings():
5570
print('')
@@ -186,6 +201,29 @@ def _get_input_parser(self) -> BaseParser:
186201
return EnvironmentParser()
187202

188203
# All other Parsers will require some input - grab it now!
204+
if not self._arguments.input_source:
205+
# Nothing passed via STDIN, and no FILENAME supplied, let's assume a default by input type for ease
206+
current_directory = os.getcwd()
207+
try:
208+
if self._arguments.input_from_conda_explicit:
209+
raise CycloneDxCmdNoInputFileSupplied('When using input from Conda Explicit, you need to pipe input'
210+
'via STDIN')
211+
elif self._arguments.input_from_conda_json:
212+
raise CycloneDxCmdNoInputFileSupplied('When using input from Conda JSON, you need to pipe input'
213+
'via STDIN')
214+
elif self._arguments.input_from_pip:
215+
self._arguments.input_source = open(os.path.join(current_directory, 'Pipfile.lock'), 'r')
216+
elif self._arguments.input_from_poetry:
217+
self._arguments.input_source = open(os.path.join(current_directory, 'poetry.lock'), 'r')
218+
elif self._arguments.input_from_requirements:
219+
self._arguments.input_source = open(os.path.join(current_directory, 'requirements.txt'), 'r')
220+
else:
221+
raise CycloneDxCmdException('Parser type could not be determined.')
222+
except FileNotFoundError as e:
223+
raise CycloneDxCmdNoInputFileSupplied(
224+
f'No input file was supplied and no input was provided on STDIN:\n{str(e)}'
225+
)
226+
189227
input_data_fh = self._arguments.input_source
190228
with input_data_fh:
191229
input_data = input_data_fh.read()
@@ -202,7 +240,7 @@ def _get_input_parser(self) -> BaseParser:
202240
elif self._arguments.input_from_requirements:
203241
return RequirementsParser(requirements_content=input_data)
204242
else:
205-
raise ValueError('Parser type could not be determined.')
243+
raise CycloneDxCmdException('Parser type could not be determined.')
206244

207245

208246
def main():

0 commit comments

Comments
 (0)