diff --git a/detect_secrets_server/actions/initialize.py b/detect_secrets_server/actions/initialize.py index 4f18597..0b33f43 100644 --- a/detect_secrets_server/actions/initialize.py +++ b/detect_secrets_server/actions/initialize.py @@ -127,6 +127,7 @@ def _clone_and_save_repo(repo): # Make the last_commit_hash of repo point to HEAD if not repo.last_commit_hash: repo.update() + return repo.save(OverrideLevel.ALWAYS) # Save the last_commit_hash, if we have nothing on file already return repo.save(OverrideLevel.NEVER) diff --git a/detect_secrets_server/actions/scan.py b/detect_secrets_server/actions/scan.py index d3a7a7e..0307296 100644 --- a/detect_secrets_server/actions/scan.py +++ b/detect_secrets_server/actions/scan.py @@ -2,6 +2,7 @@ from detect_secrets.core.log import log +from detect_secrets_server.actions.initialize import _clone_and_save_repo from detect_secrets_server.repos.base_tracked_repo import OverrideLevel from detect_secrets_server.repos.factory import tracked_repo_factory @@ -26,6 +27,10 @@ def scan_repo(args): log.error('Unable to find repo: %s', args.repo) return 1 + # if last_commit_hash is empty, re-clone and see if there's an initial commit hash + if repo.last_commit_hash is None: + _clone_and_save_repo(repo) + secrets = repo.scan( exclude_files_regex=args.exclude_files, exclude_lines_regex=args.exclude_lines, diff --git a/detect_secrets_server/storage/core/git.py b/detect_secrets_server/storage/core/git.py index 667b859..e2f68f8 100644 --- a/detect_secrets_server/storage/core/git.py +++ b/detect_secrets_server/storage/core/git.py @@ -4,6 +4,9 @@ import os import re import subprocess +import sys + +from detect_secrets.core.log import log from detect_secrets_server.constants import IGNORED_FILE_EXTENSIONS @@ -175,16 +178,39 @@ def _filter_filenames_from_diff(directory, last_commit_hash): def _git(directory, *args, **kwargs): - output = subprocess.check_output( - [ - 'git', - '--git-dir', directory, - ] + list(args), - stderr=subprocess.STDOUT - ).decode('utf-8', errors='ignore') - - # This is to fix https://github.com/matiasb/python-unidiff/issues/54 - if not kwargs.get('should_strip_output', True): - return output - - return output.strip() + try: + output = subprocess.check_output( + [ + 'git', + '--git-dir', directory, + ] + list(args), + stderr=subprocess.STDOUT + ).decode('utf-8', errors='ignore') + + # This is to fix https://github.com/matiasb/python-unidiff/issues/54 + if not kwargs.get('should_strip_output', True): + return output + return output.strip() + except subprocess.CalledProcessError as e: + error_message = e.output.decode('utf-8') + + # Catch this error, this happens during scanning and means it's an empty repo. This bails out + # of the scan process and logs error. + if re.match( + r"fatal: couldn't find remote ref (None|HEAD)", + error_message + ): + # directory is the best/only output without drastic rewrites, hashed path correlates to repo + log.error("Empty repository cannot be scanned: %s", directory) + sys.exit(1) + # TODO: This won't work if scan loops through repos, but works since it's a single scan currently + + # Catch this error, this happens during initialization and means it's an empty repo. This allows + # the repo metadata to be written to /tracked + elif re.match( + r"fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.", + error_message + ): + return None + else: + raise diff --git a/tests/actions/initialize_test.py b/tests/actions/initialize_test.py index f2c7ede..73e0755 100644 --- a/tests/actions/initialize_test.py +++ b/tests/actions/initialize_test.py @@ -224,7 +224,7 @@ def test_add_non_local_repo(self, mock_file_operations, mock_rootdir): ), ) - def test_never_override_meta_tracking_if_already_exists( + def test_override_meta_tracking_if_already_exists( self, mock_file_operations, mock_rootdir, @@ -237,7 +237,7 @@ def test_never_override_meta_tracking_if_already_exists( ): self.add_non_local_repo(mock_rootdir) - assert not mock_file_operations.write.called + assert mock_file_operations.write.called def add_non_local_repo(self, mock_rootdir): repo = 'git@github.com:yelp/detect-secrets'