Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cycode/cli/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@

# git consts
COMMIT_DIFF_DELETED_FILE_CHANGE_TYPE = 'D'
COMMIT_RANGE_ALL_COMMITS = '--all'
GIT_HEAD_COMMIT_REV = 'HEAD'
GIT_EMPTY_TREE_OBJECT = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'
EMPTY_COMMIT_SHA = '0000000000000000000000000000000000000000'
Expand Down
20 changes: 18 additions & 2 deletions cycode/cli/files_collector/commit_range_documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,10 @@ def calculate_pre_push_commit_range(push_update_details: str) -> Optional[str]:
return f'{merge_base}..{local_object_name}'

logger.debug('Failed to find merge base with any default branch')
return '--all'
return consts.COMMIT_RANGE_ALL_COMMITS
except Exception as e:
logger.debug('Failed to get repo for pre-push commit range calculation: %s', exc_info=e)
return '--all'
return consts.COMMIT_RANGE_ALL_COMMITS

# If deleting a branch (local_object_name is all zeros), no need to scan
if local_object_name == consts.EMPTY_COMMIT_SHA:
Expand Down Expand Up @@ -448,9 +448,25 @@ def parse_commit_range(commit_range: str, path: str) -> tuple[Optional[str], Opt
- 'commit' (interpreted as 'commit..HEAD')
- '..to' (interpreted as 'HEAD..to')
- 'from..' (interpreted as 'from..HEAD')
- '--all' (interpreted as 'first_commit..HEAD' to scan all commits)
"""
repo = git_proxy.get_repo(path)

# Handle '--all' special case: scan all commits from first to HEAD
# Usually represents an empty remote repository
if commit_range == consts.COMMIT_RANGE_ALL_COMMITS:
try:
head_commit = repo.rev_parse(consts.GIT_HEAD_COMMIT_REV).hexsha
all_commits = repo.git.rev_list('--reverse', head_commit).strip()
if all_commits:
first_commit = all_commits.splitlines()[0]
return first_commit, head_commit, '..'
logger.warning("No commits found for range '%s'", commit_range)
return None, None, None
except Exception as e:
logger.warning("Failed to parse commit range '%s'", commit_range, exc_info=e)
return None, None, None

separator = '..'
if '...' in commit_range:
from_spec, to_spec = commit_range.split('...', 1)
Expand Down
61 changes: 61 additions & 0 deletions tests/cli/files_collector/test_commit_range_documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,67 @@ def test_single_commit_spec(self) -> None:
parsed_from, parsed_to, separator = parse_commit_range(a, temp_dir)
assert (parsed_from, parsed_to, separator) == (a, c, '..')

def test_parse_all_for_empty_remote_scenario(self) -> None:
"""Test that '--all' is parsed correctly for empty remote repository.
This repository has one commit locally.
"""
with temporary_git_repository() as (temp_dir, repo):
# Create a local commit (simulating first commit to empty remote)
test_file = os.path.join(temp_dir, 'test.py')
with open(test_file, 'w') as f:
f.write("print('test')")

repo.index.add(['test.py'])
commit = repo.index.commit('Initial commit')

# Test that '--all' (returned by calculate_pre_push_commit_range for empty remote)
# can be parsed to a valid commit range
parsed_from, parsed_to, separator = parse_commit_range('--all', temp_dir)

# Should return first commit to HEAD (which is the only commit in this case)
assert parsed_from == commit.hexsha
assert parsed_to == commit.hexsha
assert separator == '..'

def test_parse_all_for_empty_remote_scenario_with_two_commits(self) -> None:
"""Test that '--all' is parsed correctly for empty remote repository.
This repository has two commits locally.
"""
with temporary_git_repository() as (temp_dir, repo):
# Create first commit
test_file = os.path.join(temp_dir, 'test.py')
with open(test_file, 'w') as f:
f.write("print('test')")

repo.index.add(['test.py'])
commit1 = repo.index.commit('First commit')

# Create second commit
test_file2 = os.path.join(temp_dir, 'test2.py')
with open(test_file2, 'w') as f:
f.write("print('test2')")

repo.index.add(['test2.py'])
commit2 = repo.index.commit('Second commit')

# Test that '--all' returns first commit to HEAD (second commit)
parsed_from, parsed_to, separator = parse_commit_range('--all', temp_dir)

# Should return first commit to HEAD (second commit)
assert parsed_from == commit1.hexsha # First commit
assert parsed_to == commit2.hexsha # HEAD (second commit)
assert separator == '..'

def test_parse_all_with_empty_repository_returns_none(self) -> None:
"""Test that '--all' returns None when repository has no commits."""
with temporary_git_repository() as (temp_dir, repo):
# Empty repository with no commits
parsed_from, parsed_to, separator = parse_commit_range('--all', temp_dir)
# Should return None, None, None when HEAD doesn't exist
assert parsed_from is None
assert parsed_to is None
assert separator is None


class TestParsePreReceiveInput:
"""Test the parse_pre_receive_input function with various pre-receive hook input scenarios."""
Expand Down