Repository: VirtusLab/git-machete
Pull request #1248 (2024-05-08 19:02:38)

Revert lost test coverage


Patch:
diff --git a/docs/man/git-machete.1 b/docs/man/git-machete.1
index 4d95a95..204112e 100644
--- a/docs/man/git-machete.1
+++ b/docs/man/git-machete.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "GIT-MACHETE" "1" "May 06, 2024" "" "git-machete"
+.TH "GIT-MACHETE" "1" "May 08, 2024" "" "git-machete"
 .SH NAME
 git-machete \- git-machete 3.25.3
 .sp
diff --git a/git_machete/client.py b/git_machete/client.py
index 9b38746..9612ecf 100644
--- a/git_machete/client.py
+++ b/git_machete/client.py
@@ -171,8 +171,11 @@ class MacheteClient:
                     "Slide them out from the branch layout file?" + get_pretty_choices("y", "e[dit]", "N"),
                     opt_yes_msg=None, opt_yes=False)
         else:
-            print(f"Warning: sliding invalid branches: {', '.join(bold(branch) for branch in invalid_branches)} "
-                  f"out of the branch layout file", file=sys.stderr)
+            if len(invalid_branches) == 1:
+                what = f"invalid branch {bold(invalid_branches[0])}"
+            else:
+                what = f"invalid branches {', '.join(bold(branch) for branch in invalid_branches)}"
+            print(f"Warning: sliding {what} out of the branch layout file", file=sys.stderr)
             ans = 'y'
 
         def recursive_slide_out_invalid_branches(branch_: LocalBranchShortName) -> List[LocalBranchShortName]:
diff --git a/hook_samples/post-commit b/hook_samples/post-commit
index 1e9890b..052568c 100755
--- a/hook_samples/post-commit
+++ b/hook_samples/post-commit
@@ -7,7 +7,7 @@
 git machete show current >/dev/null 2>/dev/null || exit 0
 
 # If the branch is already managed, do nothing.
-git machete is-managed 2>/dev/null && exit 0
+git machete is-managed >/dev/null 2>/dev/null && exit 0
 
 # Hooks are run by git with stdin set to /dev/null which would make it impossible for 'git machete add' to collect interactive input,
 # hence the redirect from /dev/tty.
diff --git a/tox.ini b/tox.ini
index 3fed6e6..ec5f983 100644
--- a/tox.ini
+++ b/tox.ini
@@ -100,7 +100,11 @@ commands =
 description = "Erase test coverage data"
 deps =
   -r{[requirements]dir}/coverage.txt
-commands = coverage erase
+allowlist_externals = sh
+commands =
+  coverage erase
+  # No support for globs in tox yet, alas :/
+  sh -c "rm -f {toxinidir}/.coverage.*"
 
 [coverage:run]
 dynamic_context = test_function


Test patch:
diff --git a/tests/mockers.py b/tests/mockers.py
index e53fbf4..ba4c193 100644
--- a/tests/mockers.py
+++ b/tests/mockers.py
@@ -37,35 +37,35 @@ def fixed_author_and_committer_date_in_past() -> AbstractContextManager:  # type
     )
 
 
-def launch_command(*args: str) -> str:
+def launch_command(*cmd_and_args: str) -> str:
     with io.StringIO() as out:
         with redirect_stdout(out):
             with redirect_stderr(out):
                 utils.displayed_warnings = set()
-                cli.launch(list(args))
+                cli.launch(list(cmd_and_args))
         output = out.getvalue()
         if sys.platform == 'win32':
             output = output.replace('.git\\machete', '.git/machete')
         return output
 
 
-def assert_success(cmds: Iterable[str], expected_result: str) -> None:
+def assert_success(cmd_and_args: Iterable[str], expected_result: str) -> None:
     if expected_result.startswith("\n"):
         # removeprefix is only available since Python 3.9
         expected_result = expected_result[1:]
     expected_result = textwrap.dedent(expected_result)
-    actual_result = re.sub(" +$", "", textwrap.dedent(launch_command(*cmds)), flags=re.MULTILINE)
+    actual_result = re.sub(" +$", "", textwrap.dedent(launch_command(*cmd_and_args)), flags=re.MULTILINE)
     assert actual_result == expected_result
 
 
-def assert_failure(cmds: Iterable[str], expected_result: str, expected_exception: Type[Exception] = MacheteException) -> None:
+def assert_failure(cmd_and_args: Iterable[str], expected_result: str, expected_exception: Type[Exception] = MacheteException) -> None:
     if expected_result.startswith("\n"):
         # removeprefix is only available since Python 3.9
         expected_result = expected_result[1:]
     expected_result = textwrap.dedent(expected_result)
 
     with pytest.raises(expected_exception) as e:
-        launch_command(*cmds)
+        launch_command(*cmd_and_args)
     error_message = e.value.msg  # type: ignore[attr-defined]
     error_message = re.sub(" +$", "", error_message, flags=re.MULTILINE)
     if sys.platform == 'win32':
diff --git a/tests/test_fork_point.py b/tests/test_fork_point.py
index 8255979..886c3ba 100644
--- a/tests/test_fork_point.py
+++ b/tests/test_fork_point.py
@@ -315,3 +315,16 @@ class TestForkPoint(BaseTest):
             ["fork-point"],
             first_master_commit + "\n"
         )
+
+    def test_fork_point_fallback_to_parent(self) -> None:
+        (
+            self.repo_sandbox
+            .new_branch("master").commit().push()
+            .new_branch("develop").commit().push()
+            .delete_branch("master")
+            .check_out("master")  # out of remote branch
+        )
+        rewrite_branch_layout_file("master\n\tdevelop")
+        master_commit = self.repo_sandbox.get_commit_hash("master")
+        develop_fork_point = launch_command("fork-point", "develop").rstrip()
+        assert develop_fork_point == master_commit
diff --git a/tests/test_github_checkout_prs.py b/tests/test_github_checkout_prs.py
index 7134e94..868c8ff 100644
--- a/tests/test_github_checkout_prs.py
+++ b/tests/test_github_checkout_prs.py
@@ -107,10 +107,6 @@ class TestGitHubCheckoutPRs(BaseTest):
                         chore/fields
             develop
                 enhance/feature
-                    bugfix/feature
-                        allow-ownership-link
-                            restrict_access
-                                chore/redundant_checks
             """
         rewrite_branch_layout_file(body)
 
@@ -415,13 +411,6 @@ class TestGitHubCheckoutPRs(BaseTest):
                         chore/fields
             develop
                 enhance/feature
-                    bugfix/feature
-                        allow-ownership-link
-                            restrict_access
-                                chore/redundant_checks
-            bugfix/add_user
-                testing/add_user
-                    chore/comments
             """
         rewrite_branch_layout_file(body)
 
diff --git a/tests/test_gitlab_checkout_mrs.py b/tests/test_gitlab_checkout_mrs.py
index fc74879..89b296e 100644
--- a/tests/test_gitlab_checkout_mrs.py
+++ b/tests/test_gitlab_checkout_mrs.py
@@ -109,10 +109,6 @@ class TestGitLabCheckoutMRs(BaseTest):
                         chore/fields
             develop
                 enhance/feature
-                    bugfix/feature
-                        allow-ownership-link
-                            restrict_access
-                                chore/redundant_checks
             """
         rewrite_branch_layout_file(body)
 
@@ -417,13 +413,6 @@ class TestGitLabCheckoutMRs(BaseTest):
                         chore/fields
             develop
                 enhance/feature
-                    bugfix/feature
-                        allow-ownership-link
-                            restrict_access
-                                chore/redundant_checks
-            bugfix/add_user
-                testing/add_user
-                    chore/comments
             """
         rewrite_branch_layout_file(body)
 
diff --git a/tests/test_status.py b/tests/test_status.py
index 9c97106..70788c4 100644
--- a/tests/test_status.py
+++ b/tests/test_status.py
@@ -120,6 +120,57 @@ class TestStatus(BaseTest):
         self.patch_symbol(mocker, "builtins.input", mock_input_returning_y)
         assert_success(["status"], expected_output)
 
+    def test_single_invalid_branch_non_interactive_slide_out(self) -> None:
+        (
+            self.repo_sandbox
+            .remove_remote()
+            .new_branch('master')
+            .commit()
+        )
+        body: str = \
+            """
+            master
+            \t\tfoo
+            """
+        rewrite_branch_layout_file(body)
+        expected_output = """
+            Warning: sliding invalid branch foo out of the branch layout file
+              master *
+        """
+        assert_success(["status"], expected_output)
+
+    def test_multiple_invalid_branches_non_interactive_slide_out(self) -> None:
+        (
+            self.repo_sandbox
+            .remove_remote()
+            .new_branch('master')
+            .commit()
+            .new_branch('develop')
+            .commit()
+            .new_branch('feature')
+            .commit()
+        )
+        body: str = \
+            """
+            master
+            \t\tfoo
+            \t\t\t\tbar  PR #1
+            \t\tqux
+            \t\t\t\tdevelop
+            baz
+            \t\tfeature
+            """
+        rewrite_branch_layout_file(body)
+        expected_output = """
+            Warning: sliding invalid branches foo, bar, qux, baz out of the branch layout file
+              master
+              |
+              o-develop
+
+              feature *
+        """
+        assert_success(["status"], expected_output)
+
     @pytest.mark.skipif(sys.platform == "win32", reason="Windows doesn't distinguish between executable and non-executable files")
     def test_status_advice_ignored_non_executable_hook(self) -> None:
         (