Skip to content

Commit b5e027e

Browse files
Allow users to pass in path as a file and keep old results
Signed-off-by: Raymond Baker <[email protected]>
1 parent cb803c6 commit b5e027e

File tree

6 files changed

+70
-6
lines changed

6 files changed

+70
-6
lines changed

detect_secrets/core/baseline.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def initialize(
7575
elif os.path.isfile(element):
7676
files_to_scan.append(element)
7777
else:
78-
log.error('detect-secrets: %s: No such file or directory', element)
78+
log.error('detect-secrets: "%s": No such file or directory', element)
7979

8080
if not files_to_scan:
8181
return output
@@ -262,7 +262,7 @@ def trim_baseline_of_removed_secrets(results, baseline, filelist):
262262
return updated
263263

264264

265-
def merge_baseline(old_baseline, new_baseline):
265+
def merge_baseline(old_baseline, new_baseline, keep_old_results=False):
266266
"""Updates baseline to be compatible with the latest version of
267267
detect-secrets.
268268
@@ -283,13 +283,15 @@ def merge_baseline(old_baseline, new_baseline):
283283
new_baseline['results'] = merge_results(
284284
old_baseline['results'],
285285
new_baseline['results'],
286+
keep_old_results,
286287
)
287288

288289
return new_baseline
289290

290291

291-
def merge_results(old_results, new_results):
292+
def merge_results(old_results, new_results, keep_old_results=False):
292293
"""Update results in new baseline with audit information from old baseline.
294+
Unless keep_old_results is set True
293295
294296
Secrets only appear in old baseline are ignored.
295297
@@ -302,16 +304,29 @@ def merge_results(old_results, new_results):
302304
:type new_results: dict
303305
:param new_results: results to replaced status quo
304306
307+
:type keep_old_results: bool
308+
:param keep_old_results: if set true keep old results in new_results
309+
305310
:rtype: dict
306311
"""
307312
for filename, old_secrets in old_results.items():
308-
if filename not in new_results:
313+
next_iter = False
314+
if not keep_old_results and filename not in new_results:
309315
continue
310316

311317
old_secrets_mapping = {}
312318
for old_secret in old_secrets:
313319
old_secrets_mapping[old_secret['hashed_secret']] = old_secret
314320

321+
if keep_old_results and filename not in new_results:
322+
if filename not in new_results:
323+
new_results[filename] = []
324+
new_results[filename].append(old_secret)
325+
next_iter = True
326+
327+
if next_iter:
328+
continue
329+
315330
for new_secret in new_results[filename]:
316331
if new_secret['hashed_secret'] not in old_secrets_mapping:
317332
# We don't join the two secret sets, because if the newer

detect_secrets/core/usage.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@ def add_arguments(self):
645645
self._add_opt_in_options()
646646
self._add_keyword_exclude()
647647
self._add_ghe_instance()
648+
self._add_keep_old_results()
649+
self._add_path_file()
648650

649651
return self
650652

@@ -788,3 +790,20 @@ def _add_ghe_instance(self):
788790
type=str,
789791
help='Instance URL for GHE i.e. github.ibm.com',
790792
)
793+
794+
def _add_keep_old_results(self):
795+
self.parser.add_argument(
796+
'--keep-old-results',
797+
action='store_true',
798+
help='Keep files from old result that don\'t appear in the current scan',
799+
)
800+
801+
def _add_path_file(self):
802+
self.parser.add_argument(
803+
'--path-file',
804+
type=str,
805+
help=(
806+
'Read paths from this file.'
807+
'If paths are pass into the cmdline they will be ignored'
808+
),
809+
)

detect_secrets/main.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import errno
12
import json
23
import sys
34

@@ -178,13 +179,22 @@ def _perform_scan(args, plugins, automaton, word_list_hash):
178179
if args.import_filename:
179180
_add_baseline_to_exclude_files(args)
180181

182+
paths = args.path
183+
if args.path_file:
184+
try:
185+
with open(args.path_file) as file:
186+
paths = [line.rstrip() for line in file]
187+
except FileNotFoundError:
188+
print('Path File not found: {}'.format(args.path_file), file=sys.stderr)
189+
sys.exit(errno.ENOENT)
190+
181191
new_baseline = baseline.initialize(
182192
plugins=plugins,
183193
exclude_files_regex=args.exclude_files,
184194
exclude_lines_regex=args.exclude_lines,
185195
word_list_file=args.word_list_file,
186196
word_list_hash=word_list_hash,
187-
path=args.path,
197+
path=paths,
188198
should_scan_all_files=args.all_files,
189199
output_raw=args.output_raw,
190200
output_verified_false=args.output_verified_false,
@@ -195,6 +205,7 @@ def _perform_scan(args, plugins, automaton, word_list_hash):
195205
new_baseline = baseline.merge_baseline(
196206
old_baseline,
197207
new_baseline,
208+
args.keep_old_results,
198209
)
199210

200211
return new_baseline

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pytest
1010
pyyaml
1111
responses
1212
tox-pip-extensions
13-
tox>=3.8
13+
tox<4.0
1414
unidiff
1515
ibm_db
1616
boxsdk[jwt]

tests/core/baseline_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,23 @@ def test_old_results_have_shifted_subset(self):
613613
],
614614
}
615615

616+
def test_old_results_completely_kept(self):
617+
secretA = self.get_secret()
618+
secretB = self.get_secret()
619+
620+
assert merge_results(
621+
{
622+
'filenameA': [secretA],
623+
},
624+
{
625+
'filenameB': [secretB],
626+
},
627+
True,
628+
) == {
629+
'filenameA': [secretA],
630+
'filenameB': [secretB],
631+
}
632+
616633
def test_old_results_completely_overriden(self):
617634
secretA = self.get_secret()
618635
secretB = self.get_secret()

tests/main_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ def test_reads_from_stdin(self, mock_merge_baseline):
226226
mock_merge_baseline.assert_called_once_with(
227227
{'key': 'value'},
228228
Any(dict),
229+
False,
229230
)
230231

231232
def test_reads_old_baseline_from_file(self, mock_merge_baseline):
@@ -243,6 +244,7 @@ def test_reads_old_baseline_from_file(self, mock_merge_baseline):
243244
mock_merge_baseline.assert_called_once_with(
244245
{'key': 'value'},
245246
Any(dict),
247+
False,
246248
)
247249

248250
def test_reads_non_existed_baseline_from_file(

0 commit comments

Comments
 (0)