Skip to content

Commit 2e06c6d

Browse files
authored
:merge_arrow_right_hook: Merge pull request #188 from dgzlopes/fix-180-multiple-file-support
Add multiple file support
2 parents 1389360 + 75cb635 commit 2e06c6d

File tree

5 files changed

+54
-20
lines changed

5 files changed

+54
-20
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ $ detect-secrets scan --update .secrets.baseline
7373

7474
### Command Line
7575

76-
`detect-secrets` is designed to be used as a git pre-commit hook, but you can also invoke `detect-secrets scan [path]` directly (`path` defaults to `.` if not specified).
76+
`detect-secrets` is designed to be used as a git pre-commit hook, but you can also invoke `detect-secrets scan [path]` directly being `path` the file(s) and/or directory(ies) to scan (`path` defaults to `.` if not specified).
7777

7878
It should be noted that by default, `detect-secrets scan` only operates on files that are tracked by git. So if you intend to scan files outside of a git repository, you will need to pass the `--all-files` flag.
7979

detect_secrets/core/baseline.py

+16-9
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
import re
66
import subprocess
77

8+
from detect_secrets.core.log import get_logger
89
from detect_secrets.core.secrets_collection import SecretsCollection
910

11+
log = get_logger(format_string='%(message)s')
12+
1013

1114
def initialize(
15+
path,
1216
plugins,
1317
exclude_files_regex=None,
1418
exclude_lines_regex=None,
15-
path='.',
1619
scan_all_files=False,
1720
):
1821
"""Scans the entire codebase for secrets, and returns a
@@ -23,7 +26,7 @@ def initialize(
2326
2427
:type exclude_files_regex: str|None
2528
:type exclude_lines_regex: str|None
26-
:type path: str
29+
:type path: list
2730
:type scan_all_files: bool
2831
2932
:rtype: SecretsCollection
@@ -34,13 +37,17 @@ def initialize(
3437
exclude_lines=exclude_lines_regex,
3538
)
3639

37-
if os.path.isfile(path):
38-
# This option allows for much easier adhoc usage.
39-
files_to_scan = [path]
40-
elif scan_all_files:
41-
files_to_scan = _get_files_recursively(path)
42-
else:
43-
files_to_scan = _get_git_tracked_files(path)
40+
files_to_scan = list()
41+
for element in path:
42+
if os.path.isdir(element):
43+
if scan_all_files:
44+
files_to_scan.extend(_get_files_recursively(element))
45+
else:
46+
files_to_scan.extend(_get_git_tracked_files(element))
47+
elif os.path.isfile(element):
48+
files_to_scan.append(element)
49+
else:
50+
log.error("detect-secrets: " + element + ": No such file or directory")
4451

4552
if not files_to_scan:
4653
return output

detect_secrets/core/usage.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def add_arguments(self):
120120
def _add_initialize_baseline_argument(self):
121121
self.parser.add_argument(
122122
'path',
123-
nargs='?',
123+
nargs='*',
124124
default='.',
125125
help=(
126126
'Scans the entire codebase and outputs a snapshot of '

tests/core/baseline_test.py

+35-8
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,26 @@ def setup(self):
3131

3232
def get_results(
3333
self,
34-
path='./test_data/files',
34+
path=['./test_data/files'],
3535
exclude_files_regex=None,
3636
scan_all_files=False,
3737
):
3838
return baseline.initialize(
39+
path,
3940
self.plugins,
40-
path=path,
4141
exclude_files_regex=exclude_files_regex,
4242
scan_all_files=scan_all_files,
4343
).json()
4444

4545
@pytest.mark.parametrize(
4646
'path',
4747
[
48-
'./test_data/files',
48+
[
49+
'./test_data/files',
4950
50-
# Test relative paths
51-
'test_data/../test_data/files/tmp/..',
51+
# Test relative paths
52+
'test_data/../test_data/files/tmp/..',
53+
],
5254
],
5355
)
5456
def test_basic_usage(self, path):
@@ -58,6 +60,31 @@ def test_basic_usage(self, path):
5860
assert len(results['test_data/files/file_with_secrets.py']) == 1
5961
assert len(results['test_data/files/tmp/file_with_secrets.py']) == 2
6062

63+
def test_with_multiple_files(self):
64+
results = self.get_results(path=[
65+
'test_data/files/file_with_secrets.py',
66+
'test_data/files/tmp/file_with_secrets.py',
67+
])
68+
69+
assert len(results['test_data/files/file_with_secrets.py']) == 1
70+
assert len(results['test_data/files/tmp/file_with_secrets.py']) == 2
71+
assert 'test_data/files/file_with_secrets.py' in results
72+
assert 'test_data/files/tmp/file_with_secrets.py' in results
73+
74+
def test_with_multiple_non_existent_files(self):
75+
results = self.get_results(path=['non-existent-file.A', 'non-existent-file.B'])
76+
77+
# No expected results, because files don't exist
78+
assert not results
79+
80+
def test_with_folders_and_files(self):
81+
results = self.get_results(path=['test_data/', 'non-existent-file.B'])
82+
83+
assert 'test_data/files/file_with_secrets.py' in results
84+
assert 'test_data/files/tmp/file_with_secrets.py' in results
85+
assert 'test_data/files/file_with_no_secrets.py' not in results
86+
assert 'non-existent-file.B' not in results
87+
6188
def test_exclude_regex(self):
6289
results = self.get_results(exclude_files_regex='tmp*')
6390

@@ -82,7 +109,7 @@ def test_no_files_in_git_repo(self):
82109
),
83110
),
84111
):
85-
results = self.get_results(path='will_be_mocked')
112+
results = self.get_results(path=['will_be_mocked'])
86113

87114
assert not results
88115

@@ -94,12 +121,12 @@ def test_single_non_tracked_git_file_should_work(self):
94121
'Super hidden value "BEEF0123456789a"',
95122
'detect_secrets.core.secrets_collection.codecs.open',
96123
):
97-
results = self.get_results('will_be_mocked')
124+
results = self.get_results(path=['will_be_mocked'])
98125

99126
assert len(results['will_be_mocked']) == 1
100127

101128
def test_scan_all_files(self):
102-
results = self.get_results(path='test_data/files', scan_all_files=True)
129+
results = self.get_results(path=['test_data/files'], scan_all_files=True)
103130
assert len(results.keys()) == 2
104131

105132

tests/main_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def test_scan_with_rootdir(self, mock_baseline_initialize):
4141
plugins=Any(tuple),
4242
exclude_files_regex=None,
4343
exclude_lines_regex=None,
44-
path='test_data',
44+
path=['test_data'],
4545
scan_all_files=False,
4646
)
4747

0 commit comments

Comments
 (0)