diff --git a/jupyterlab_git/git.py b/jupyterlab_git/git.py index a4ae5e9e..d0b7369b 100644 --- a/jupyterlab_git/git.py +++ b/jupyterlab_git/git.py @@ -486,6 +486,13 @@ def remove_cell_ids(nb): return {"base": prev_nb, "diff": thediff} + async def _is_first_commit(self, path: str) -> bool: + """Return True if repo has no commits yet.""" + code, _, _ = await self.__execute( + ["git", "rev-parse", "--verify", "HEAD"], cwd=path + ) + return code != 0 + async def status(self, path: str) -> dict: """ Execute git status command & return the result. @@ -501,14 +508,19 @@ async def status(self, path: str) -> dict: } # Add attribute `is_binary` - command = [ # Compare stage to an empty tree see `_is_binary` - "git", - "diff", - "--numstat", - "-z", - "--cached", - "4b825dc642cb6eb9a060e54bf8d69288fbee4904", - ] + first_commit = await self._is_first_commit(path) + if first_commit: + # only first commit has to compare to an empty tree + command = [ # Compare stage to an empty tree see `_is_binary` + "git", + "diff", + "--numstat", + "-z", + "--cached", + "4b825dc642cb6eb9a060e54bf8d69288fbee4904", + ] + else: + command = ["git", "diff", "--numstat", "-z", "--cached"] text_code, text_output, _ = await self.__execute(command, cwd=path) are_binary = dict() @@ -1137,7 +1149,7 @@ async def checkout_branch(self, branchname, path): is_remote_branch = self._is_remote_branch(reference_name) if is_remote_branch: - local_branchname = branchname.split("/")[-1] + local_branchname = "/".join(branchname.split("/")[1:]) cmd = ["git", "checkout", "-B", local_branchname, branchname] else: cmd = ["git", "checkout", branchname] diff --git a/jupyterlab_git/tests/test_branch.py b/jupyterlab_git/tests/test_branch.py index c78d62e6..fbb04860 100644 --- a/jupyterlab_git/tests/test_branch.py +++ b/jupyterlab_git/tests/test_branch.py @@ -174,6 +174,48 @@ async def test_checkout_branch_remoteref_success(): assert {"code": rc, "message": stdout_message} == actual_response +@pytest.mark.asyncio +async def test_checkout_branch_remoteref_success_when_has_slash(): + branch = "origin/test-branch/test" + local_branch = "test-branch/test" + curr_path = str(Path("/bin/test_curr_path")) + stdout_message = "checkout output from git" + stderr_message = "" + rc = 0 + + with patch("jupyterlab_git.git.execute") as mock_execute: + with patch.object( + Git, + "_get_branch_reference", + return_value=maybe_future("refs/remotes/remote_branch"), + ) as mock__get_branch_reference: + # Given + mock_execute.return_value = maybe_future( + (rc, stdout_message, stderr_message) + ) + + # When + actual_response = await Git().checkout_branch( + branchname=branch, path=curr_path + ) + + # Then + mock__get_branch_reference.assert_has_calls([call(branch, curr_path)]) + + cmd = ["git", "checkout", "-B", local_branch, branch] + mock_execute.assert_called_once_with( + cmd, + cwd=str(Path("/bin") / "test_curr_path"), + timeout=20, + env=None, + username=None, + password=None, + is_binary=False, + ) + + assert {"code": rc, "message": stdout_message} == actual_response + + @pytest.mark.asyncio async def test_checkout_branch_headsref_failure(): branch = "test-branch"