Skip to content

Commit

Permalink
Issue #618: Add new subcommand git machete list childless (#632)
Browse files Browse the repository at this point in the history
  • Loading branch information
amalota authored Aug 17, 2022
1 parent b4985ab commit 3d5a411
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 9 deletions.
2 changes: 2 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## New in git-machete 3.12.0

- added: subcommand `git machete list childless`

## New in git-machete 3.11.6

- added: package for Ubuntu 22.04 LTS
Expand Down
2 changes: 1 addition & 1 deletion completion/git-machete.completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ _git_machete() {
local cmds="add advance anno clean d delete-unmanaged diff discover e edit file fork-point g github go help is-managed l list log reapply s show slide-out squash status traverse update version"
local help_topics="$cmds config format hooks"

local categories="addable managed slidable slidable-after unmanaged with-overridden-fork-point"
local categories="addable childless managed slidable slidable-after unmanaged with-overridden-fork-point"
local directions="down first last next prev root up"
local github_subcommands="anno-prs checkout-prs create-pr retarget-pr sync"
local locations="current $directions"
Expand Down
1 change: 1 addition & 0 deletions completion/git-machete.completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ __git_machete_categories() {
# TODO (#115): complete slidable-after's argument
categories=(
'addable:all branches (local or remote) than can be added to the definition file'
'childless:all branches that do not possess child branches'
'managed:all branches that appear in the definition file'
'slidable:all managed branches that have exactly one upstream and one downstream (i.e. the ones that can be slid out with slide-out command)'
'slidable-after:the downstream branch of the given branch, if it exists and is its only downstream (i.e. the one that can be slid out immediately following <branch>)'
Expand Down
13 changes: 7 additions & 6 deletions completion/git-machete.fish
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,14 @@ complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand

# git machete list
complete -c git -n "__fish_git_using_command machete; and not __fish_seen_subcommand_from $__mcht_commands" -f -a list -d 'List all branches that fall into one of pre-defined categories (mostly for internal use)'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a addable -d 'all branches (local or remote) than can be added to the definition file'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a managed -d 'all branches that appear in the definition file'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a slidable -d 'all managed branches that have an upstream and can be slid out with slide-out command'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a slidable-after -d 'the downstream branch of the <branch>, if it exists and is the only downstream of <branch> (i.e. the one that can be slid out immediately following <branch>)'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a addable
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a childless -d 'all branches (local or remote) than can be added to the definition file'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a managed -d 'all branches that appear in the definition file'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a slidable -d 'all managed branches that have an upstream and can be slid out with slide-out command'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a slidable-after -d 'the downstream branch of the <branch>, if it exists and is the only downstream of <branch> (i.e. the one that can be slid out immediately following <branch>)'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and __fish_seen_subcommand_from slidable-after" -f -a '(__fish_git_local_branches)'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a unmanaged -d 'all local branches that don\'t appear in the definition file'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a with-overridden-fork-point -d 'all local branches that have a fork point override set up (even if this override does not affect the location of their fork point anymore).'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a unmanaged -d 'all local branches that don\'t appear in the definition file'
complete -c git -n "__fish_git_using_command machete; and __fish_seen_subcommand_from list; and not __fish_seen_subcommand_from addable childless managed slidable slidable-after unmanaged with-overridden-fork-point" -f -a with-overridden-fork-point -d 'all local branches that have a fork point override set up (even if this override does not affect the location of their fork point anymore).'

# git machete log
complete -c git -n "__fish_git_using_command machete; and not __fish_seen_subcommand_from $__mcht_commands" -f -a log -d 'Log the part of history specific to the given branch'
Expand Down
3 changes: 2 additions & 1 deletion docs/source/cli_help/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ list
git machete list <category>
where <category> is one of: ``addable``, ``managed``, ``slidable``, ``slidable-after <branch>``, ``unmanaged``, ``with-overridden-fork-point``.
where <category> is one of: ``addable``, ``childless``, ``managed``, ``slidable``, ``slidable-after <branch>``, ``unmanaged``, ``with-overridden-fork-point``.

Lists all branches that fall into one of the specified categories:

* ``addable``: all branches (local or remote) than can be added to the definition file,
* ``childless``: all branches that do not possess child branches,
* ``managed``: all branches that appear in the definition file,
* ``slidable``: all managed branches that have an upstream and can be slid out with :ref:`slide-out` command
* ``slidable-after <branch>``: the downstream branch of the <branch>, if it exists and is the only downstream of <branch> (i.e. the one that can be slid out immediately following <branch>),
Expand Down
4 changes: 3 additions & 1 deletion git_machete/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def create_cli_parser() -> argparse.ArgumentParser:
list_parser.add_argument(
'category',
choices=[
'addable', 'managed', 'slidable', 'slidable-after', 'unmanaged',
'addable', 'childless', 'managed', 'slidable', 'slidable-after', 'unmanaged',
'with-overridden-fork-point']
)
list_parser.add_argument('branch', nargs='?', default=argparse.SUPPRESS)
Expand Down Expand Up @@ -682,6 +682,8 @@ def strip_remote_name(remote_branch: RemoteBranchShortName) -> LocalBranchShortN
remote_counterparts_of_local_branches})
res = excluding(git.get_local_branches(), machete_client.managed_branches) + list(
map(strip_remote_name, qualifying_remote_branches))
elif category == "childless":
res = machete_client.get_childless_branches()
elif category == "managed":
res = machete_client.managed_branches
elif category == "slidable":
Expand Down
4 changes: 4 additions & 0 deletions git_machete/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ def up_branch(self) -> Dict[LocalBranchShortName, Optional[LocalBranchShortName]
def up_branch(self, val: Dict[LocalBranchShortName, Optional[LocalBranchShortName]]) -> None:
self._up_branch = val

def get_childless_branches(self) -> List[LocalBranchShortName]:
parent_branches = [parent_branch for parent_branch, child_branches in self.__down_branches.items() if len(child_branches) > 0]
return excluding(self.managed_branches, parent_branches)

def expect_in_managed_branches(self, branch: LocalBranchShortName) -> None:
if branch not in self.managed_branches:
raise MacheteException(
Expand Down
1 change: 1 addition & 0 deletions git_machete/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@
Lists all branches that fall into one of the specified categories:
* `addable`: all branches (local or remote) than can be added to the definition file,
* `childless`: all branches that do not possess child branches,
* `managed`: all branches that appear in the definition file,
* `slidable`: all managed branches that have an upstream and can be slid out with `slide-out` command
* `slidable-after <branch>`: the downstream branch of the <branch>, if it exists and is the only downstream of <branch> (i.e. the one that can be slid out immediately following <branch>),
Expand Down
143 changes: 143 additions & 0 deletions tests/test_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
from textwrap import dedent
from typing import Any

from .mockers import (GitRepositorySandbox, assert_command, launch_command, mock_run_cmd, rewrite_definition_file)


class TestList:

def setup_method(self) -> None:
self.repo_sandbox = GitRepositorySandbox()

(
self.repo_sandbox
# Create the remote and sandbox repos, chdir into sandbox repo
.new_repo(self.repo_sandbox.remote_path, "--bare")
.new_repo(self.repo_sandbox.local_path)
.execute(f"git remote add origin {self.repo_sandbox.remote_path}")
.execute('git config user.email "tester@test.com"')
.execute('git config user.name "Tester Test"')
)

def test_list(self, mocker: Any) -> None:
"""
Verify behaviour of a 'git machete list' command.
"""
mocker.patch('git_machete.utils.run_cmd', mock_run_cmd) # to hide git outputs in tests

(
self.repo_sandbox.new_branch("master")
.commit("master commit.")
.new_branch("develop")
.commit("develop commit.")
.new_branch("feature_0")
.commit("feature_0 commit.")
.new_branch("feature_0_0")
.commit("feature_0_0 commit.")
.new_branch("feature_0_0_0")
.commit("feature_0_0_0 commit.")
.check_out("feature_0")
.new_branch("feature_0_1")
.commit("feature_0_1 commit.")
.check_out("develop")
.new_branch("feature_1")
.commit("feature_1 commit.")
)

body: str = \
"""
master
develop
feature_0
feature_0_0
feature_0_0_0
feature_0_1
feature_1
"""
body = dedent(body)
rewrite_definition_file(body)

(
self.repo_sandbox.check_out("develop")
.new_branch("feature_2")
.commit("feature_2 commit.")
)

expected_output = """
master
develop
feature_0
feature_0_0
feature_0_0_0
feature_0_1
feature_1
"""
assert_command(
['list', 'managed'],
expected_output,
indent=''
)

expected_output = """
feature_2
"""
assert_command(
['list', 'addable'],
expected_output,
indent=''
)

expected_output = """
master
feature_0_0_0
feature_0_1
feature_1
"""
assert_command(
['list', 'childless'],
expected_output,
indent=''
)

expected_output = """
feature_0
feature_0_0
feature_0_0_0
feature_0_1
feature_1
"""
assert_command(
['list', 'slidable'],
expected_output,
indent=''
)

expected_output = """
feature_0_0_0
"""
assert_command(
['list', 'slidable-after', 'feature_0_0'],
expected_output,
indent=''
)

expected_output = """
feature_2
"""
assert_command(
['list', 'unmanaged'],
expected_output,
indent=''
)

self.repo_sandbox.check_out("feature_1")
launch_command('fork-point', '--override-to-inferred')

expected_output = """
feature_1
"""
assert_command(
['list', 'with-overridden-fork-point'],
expected_output,
indent=''
)

0 comments on commit 3d5a411

Please sign in to comment.