Skip to content

Commit ba83554

Browse files
committed
fix parsing of commit ranges
1 parent 719e376 commit ba83554

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

cycode/cli/apps/scan/commit_range_scanner.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
get_diff_file_content,
2525
get_diff_file_path,
2626
get_pre_commit_modified_documents,
27-
parse_commit_range,
27+
parse_commit_range_sast,
28+
parse_commit_range_sca,
2829
)
2930
from cycode.cli.files_collector.file_excluder import excluder
3031
from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip
@@ -173,7 +174,7 @@ def _scan_commit_range_documents(
173174
def _scan_sca_commit_range(ctx: typer.Context, repo_path: str, commit_range: str, **_) -> None:
174175
scan_parameters = get_scan_parameters(ctx, (repo_path,))
175176

176-
from_commit_rev, to_commit_rev = parse_commit_range(commit_range, repo_path)
177+
from_commit_rev, to_commit_rev = parse_commit_range_sca(commit_range, repo_path)
177178
from_commit_documents, to_commit_documents, _ = get_commit_range_modified_documents(
178179
ctx.obj['progress_bar'], ScanProgressBarSection.PREPARE_LOCAL_FILES, repo_path, from_commit_rev, to_commit_rev
179180
)
@@ -203,8 +204,9 @@ def _scan_secret_commit_range(
203204
def _scan_sast_commit_range(ctx: typer.Context, repo_path: str, commit_range: str, **_) -> None:
204205
scan_parameters = get_scan_parameters(ctx, (repo_path,))
205206

206-
from_commit_rev, to_commit_rev = parse_commit_range(commit_range, repo_path)
207-
_, commit_documents, diff_documents = get_commit_range_modified_documents(
207+
from_commit_rev, to_commit_rev = parse_commit_range_sast(commit_range, repo_path)
208+
# we are using from_commit_documents here because of flipped mess with R=True, differences in parsing commit ranges
209+
commit_documents, _, diff_documents = get_commit_range_modified_documents(
208210
ctx.obj['progress_bar'], ScanProgressBarSection.PREPARE_LOCAL_FILES, repo_path, from_commit_rev, to_commit_rev
209211
)
210212
commit_documents = excluder.exclude_irrelevant_documents_to_scan(consts.SAST_SCAN_TYPE, commit_documents)

cycode/cli/files_collector/commit_range_documents.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,53 @@ def get_pre_commit_modified_documents(
236236
return git_head_documents, pre_committed_documents, diff_documents
237237

238238

239-
def parse_commit_range(commit_range: str, path: str) -> tuple[str, str]:
240-
from_commit_rev = None
241-
to_commit_rev = None
239+
def parse_commit_range_sca(commit_range: str, path: str) -> tuple[Optional[str], Optional[str]]:
240+
# FIXME(MarshalX): i truly believe that this function does NOT work as expected
241+
# it does not handle cases like 'A..B' correctly
242+
# i leave it as it for SCA to not break anything
243+
# the more correct approach is implemented for SAST
244+
from_commit_rev = to_commit_rev = None
242245

243246
for commit in git_proxy.get_repo(path).iter_commits(rev=commit_range):
244247
if not to_commit_rev:
245248
to_commit_rev = commit.hexsha
246249
from_commit_rev = commit.hexsha
247250

248251
return from_commit_rev, to_commit_rev
252+
253+
254+
def parse_commit_range_sast(commit_range: str, path: str) -> tuple[Optional[str], Optional[str]]:
255+
"""Parses a git commit range string and returns the full SHAs for the 'from' and 'to' commits.
256+
257+
Supports:
258+
- 'from..to'
259+
- 'from...to'
260+
- 'commit' (interpreted as 'commit..HEAD')
261+
- '..to' (interpreted as 'HEAD..to')
262+
- 'from..' (interpreted as 'from..HEAD')
263+
"""
264+
repo = git_proxy.get_repo(path)
265+
266+
if '...' in commit_range:
267+
from_spec, to_spec = commit_range.split('...', 1)
268+
elif '..' in commit_range:
269+
from_spec, to_spec = commit_range.split('..', 1)
270+
else:
271+
# Git commands like 'git diff <commit>' compare against HEAD.
272+
from_spec = commit_range
273+
to_spec = 'HEAD'
274+
275+
# If a spec is empty (e.g., from '..master'), default it to 'HEAD'
276+
if not from_spec:
277+
from_spec = 'HEAD'
278+
if not to_spec:
279+
to_spec = 'HEAD'
280+
281+
try:
282+
# Use rev_parse to resolve each specifier to its full commit SHA
283+
from_commit_rev = repo.rev_parse(from_spec).hexsha
284+
to_commit_rev = repo.rev_parse(to_spec).hexsha
285+
return from_commit_rev, to_commit_rev
286+
except git_proxy.get_git_command_error() as e:
287+
logger.warning("Failed to parse commit range '%s'", commit_range, exc_info=e)
288+
return None, None

0 commit comments

Comments
 (0)