diff --git a/src/stack_pr/cli.py b/src/stack_pr/cli.py index d068998..32afe35 100755 --- a/src/stack_pr/cli.py +++ b/src/stack_pr/cli.py @@ -69,6 +69,7 @@ get_current_branch_name, get_gh_username, get_uncommitted_changes, + is_rebase_in_progress, ) from stack_pr.shell_commands import ( get_command_output, @@ -170,6 +171,10 @@ Please commit or stash them before working with stacks. """ +ERROR_REBASE_IN_PROGRESS = """Cannot submit while in the middle of a rebase. + +Please complete or abort the current rebase first. +""" UPDATE_STACK_TIP = """ If you'd like to push your local changes first, you can use the following command to update the stack: $ stack-pr export -B {top_commit}~{stack_size} -H {top_commit}""" @@ -933,6 +938,11 @@ def command_submit( a draft. """ log(h("SUBMIT"), level=1) + + if is_rebase_in_progress(): + error(ERROR_REBASE_IN_PROGRESS) + sys.exit(1) + current_branch = get_current_branch_name() if should_update_local_base( diff --git a/src/stack_pr/git.py b/src/stack_pr/git.py index 3cb6ce3..cd4714a 100644 --- a/src/stack_pr/git.py +++ b/src/stack_pr/git.py @@ -213,3 +213,16 @@ def get_changed_dirs( files changed. """ return {Path(file.parts[0]) for file in get_changed_files(base, repo_dir)} + + +def is_rebase_in_progress(repo_dir: Path | None = None) -> bool: + """Check if a rebase operation is currently in progress. + + Args: + repo_dir: path to the repo. Defaults to the current working directory. + + Returns: + True if a rebase is in progress, False otherwise. + """ + git_dir = Path(".git") if repo_dir is None else repo_dir / ".git" + return (git_dir / "rebase-merge").exists() or (git_dir / "rebase-apply").exists() diff --git a/tests/test_misc.py b/tests/test_misc.py index 93d8ee9..5517c10 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,4 +1,5 @@ import sys +import tempfile from pathlib import Path sys.path.append(str(Path(__file__).parent.parent / "src")) @@ -12,7 +13,7 @@ get_gh_username, get_taken_branch_ids, ) -from stack_pr.git import git_config +from stack_pr.git import git_config, is_rebase_in_progress @pytest.fixture(scope="module") @@ -90,3 +91,35 @@ def test_generate_available_branch_name() -> None: "refs/remotes/origin/TestBot-stack-134", ] assert generate_available_branch_name(refs, template) == "TestBot-stack-135" + + +def test_is_rebase_in_progress() -> None: + """Test the is_rebase_in_progress function with different git states.""" + with tempfile.TemporaryDirectory() as temp_dir: + repo_dir = Path(temp_dir) + git_dir = repo_dir / ".git" + git_dir.mkdir() + + # Test no rebase in progress + assert not is_rebase_in_progress(repo_dir) + + # Test rebase-merge directory exists + rebase_merge_dir = git_dir / "rebase-merge" + rebase_merge_dir.mkdir() + assert is_rebase_in_progress(repo_dir) + + # Clean up and test rebase-apply directory + rebase_merge_dir.rmdir() + assert not is_rebase_in_progress(repo_dir) + + rebase_apply_dir = git_dir / "rebase-apply" + rebase_apply_dir.mkdir() + assert is_rebase_in_progress(repo_dir) + + # Test both directories exist + rebase_merge_dir.mkdir() + assert is_rebase_in_progress(repo_dir) + + # Test with None repo_dir (current directory) + # This should not raise an error even if .git doesn't exist in cwd + assert not is_rebase_in_progress(None)