|
14 | 14 | calculate_pre_push_commit_range, |
15 | 15 | get_diff_file_path, |
16 | 16 | get_safe_head_reference_for_diff, |
| 17 | + parse_commit_range, |
17 | 18 | parse_pre_push_input, |
18 | 19 | ) |
19 | 20 | from cycode.cli.utils.path_utils import get_path_by_os |
|
22 | 23 | @contextmanager |
23 | 24 | def git_repository(path: str) -> Generator[Repo, None, None]: |
24 | 25 | """Context manager for Git repositories that ensures proper cleanup on Windows.""" |
25 | | - repo = Repo.init(path) |
| 26 | + # Ensure the initialized repository uses 'main' as the default branch |
| 27 | + repo = Repo.init(path, b='main') |
26 | 28 | try: |
27 | 29 | yield repo |
28 | 30 | finally: |
@@ -539,8 +541,8 @@ def test_calculate_range_for_new_branch_with_merge_base(self) -> None: |
539 | 541 | repo.index.add(['feature.py']) |
540 | 542 | feature_commit = repo.index.commit('Add feature') |
541 | 543 |
|
542 | | - # Switch back to master to simulate we're pushing a feature branch |
543 | | - repo.heads.master.checkout() |
| 544 | + # Switch back to the default branch to simulate pushing the feature branch |
| 545 | + repo.heads.main.checkout() |
544 | 546 |
|
545 | 547 | # Test new branch push |
546 | 548 | push_details = f'refs/heads/feature {feature_commit.hexsha} refs/heads/feature {consts.EMPTY_COMMIT_SHA}' |
@@ -805,3 +807,67 @@ def test_simulate_pre_push_hook_input_format(self) -> None: |
805 | 807 | parts = push_input.split() |
806 | 808 | expected_range = f'{parts[3]}..{parts[1]}' |
807 | 809 | assert commit_range == expected_range |
| 810 | + |
| 811 | + |
| 812 | +class TestParseCommitRange: |
| 813 | + """Tests to validate unified parse_commit_range behavior matches git semantics.""" |
| 814 | + |
| 815 | + def _make_linear_history(self, repo: Repo, base_dir: str) -> tuple[str, str, str]: |
| 816 | + """Create three linear commits A -> B -> C and return their SHAs.""" |
| 817 | + a_file = os.path.join(base_dir, 'a.txt') |
| 818 | + with open(a_file, 'w') as f: |
| 819 | + f.write('A') |
| 820 | + repo.index.add(['a.txt']) |
| 821 | + a = repo.index.commit('A') |
| 822 | + |
| 823 | + with open(a_file, 'a') as f: |
| 824 | + f.write('B') |
| 825 | + repo.index.add(['a.txt']) |
| 826 | + b = repo.index.commit('B') |
| 827 | + |
| 828 | + with open(a_file, 'a') as f: |
| 829 | + f.write('C') |
| 830 | + repo.index.add(['a.txt']) |
| 831 | + c = repo.index.commit('C') |
| 832 | + |
| 833 | + return a.hexsha, b.hexsha, c.hexsha |
| 834 | + |
| 835 | + def test_two_dot_linear_history(self) -> None: |
| 836 | + """For 'A..C', expect (A,C) in linear history.""" |
| 837 | + with temporary_git_repository() as (temp_dir, repo): |
| 838 | + a, b, c = self._make_linear_history(repo, temp_dir) |
| 839 | + |
| 840 | + parsed_from, parsed_to = parse_commit_range(f'{a}..{c}', temp_dir) |
| 841 | + assert (parsed_from, parsed_to) == (a, c) |
| 842 | + |
| 843 | + def test_three_dot_linear_history(self) -> None: |
| 844 | + """For 'A...C' in linear history, expect (A,C).""" |
| 845 | + with temporary_git_repository() as (temp_dir, repo): |
| 846 | + a, b, c = self._make_linear_history(repo, temp_dir) |
| 847 | + |
| 848 | + parsed_from, parsed_to = parse_commit_range(f'{a}...{c}', temp_dir) |
| 849 | + assert (parsed_from, parsed_to) == (a, c) |
| 850 | + |
| 851 | + def test_open_right_linear_history(self) -> None: |
| 852 | + """For 'A..', expect (A,HEAD=C).""" |
| 853 | + with temporary_git_repository() as (temp_dir, repo): |
| 854 | + a, b, c = self._make_linear_history(repo, temp_dir) |
| 855 | + |
| 856 | + parsed_from, parsed_to = parse_commit_range(f'{a}..', temp_dir) |
| 857 | + assert (parsed_from, parsed_to) == (a, c) |
| 858 | + |
| 859 | + def test_open_left_linear_history(self) -> None: |
| 860 | + """For '..C' where HEAD==C, expect (HEAD=C,C).""" |
| 861 | + with temporary_git_repository() as (temp_dir, repo): |
| 862 | + a, b, c = self._make_linear_history(repo, temp_dir) |
| 863 | + |
| 864 | + parsed_from, parsed_to = parse_commit_range(f'..{c}', temp_dir) |
| 865 | + assert (parsed_from, parsed_to) == (c, c) |
| 866 | + |
| 867 | + def test_single_commit_spec(self) -> None: |
| 868 | + """For 'A', expect (A,HEAD=C).""" |
| 869 | + with temporary_git_repository() as (temp_dir, repo): |
| 870 | + a, b, c = self._make_linear_history(repo, temp_dir) |
| 871 | + |
| 872 | + parsed_from, parsed_to = parse_commit_range(a, temp_dir) |
| 873 | + assert (parsed_from, parsed_to) == (a, c) |
0 commit comments