Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.38.2

- improved: every time a branch is checked out, a `Checking out <branch>... OK` message is printed out for consistency

## New in git-machete 3.38.1

- added: a GitHub-viewable tutorial under `docs/tutorial` (suggested by @joeprivett)
Expand Down
4 changes: 2 additions & 2 deletions ci/snap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ See [Snapcraft forum thread](https://forum.snapcraft.io/t/is-there-any-way-to-ex

To generate and upload a new Snapcraft token:

- Install [`snapcraft`](https://snapcraft.io/docs/installing-snapcraft).
- Install [`snapcraft`](https://snapcraft.io/docs/installing-snapcraft) (`brew install snapcraft` on macOS).

- Move `~/.snapcraft-credentials` (if exists) to `~/.snapcraft-credentials~`
- Move `~/.snapcraft-credentials` (if exist) to `~/.snapcraft-credentials~`

- Generate a new token:
```shell
Expand Down
8 changes: 5 additions & 3 deletions git_machete/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
UnderlyingGitException, UnexpectedMacheteException)
from .generated_docs import long_docs, short_docs
from .git_operations import AnyRevision, GitContext, LocalBranchShortName
from .utils import bold, fmt, underline, warn
from .utils import bold, fmt, green_ok, print_no_newline, underline, warn

T = TypeVar('T')

Expand Down Expand Up @@ -783,16 +783,18 @@ def warn_on_deprecation(*, flag: str, revision: AnyRevision, revision_str: str)
# with pick_if_multiple=True, there returned list will have exactly one element
dest = go_client.parse_direction(parsed_cli.direction, branch=current_branch, allow_current=False, pick_if_multiple=True)[0]
if dest != current_branch:
print_no_newline(f"Checking out {bold(dest)}... ")
git.checkout(dest)
print(green_ok())
else:
interactive_client = GoInteractiveMacheteClient(git)
interactive_client.read_branch_layout_file()
interactive_client.expect_at_least_one_managed_branch()
dest_ = interactive_client.go_interactive()
if dest_ is not None and dest_ != current_branch:
print(f"Checking out {bold(dest_)}... ", end='', flush=True)
print_no_newline(f"Checking out {bold(dest_)}... ")
git.checkout(dest_)
print(fmt('<green><b>OK</b></green>'))
print(green_ok())
elif cmd == "is-managed":
is_managed_client = MacheteClient(git)
is_managed_client.read_branch_layout_file()
Expand Down
8 changes: 7 additions & 1 deletion git_machete/client/slide_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from git_machete.client.base import MacheteClient, SquashMergeDetection
from git_machete.exceptions import MacheteException
from git_machete.git_operations import AnyRevision, LocalBranchShortName
from git_machete.utils import bold, fmt
from git_machete.utils import bold, fmt, green_ok, print_no_newline


class SlideOutMacheteClient(MacheteClient):
Expand Down Expand Up @@ -99,10 +99,14 @@ def slide_out(self,
# Check out new upstream if we were on a slid-out branch, but only if there is an upstream
if self._git.get_current_branch_or_none() in branches_to_slide_out:
if new_upstream is not None:
print_no_newline(f"Checking out {bold(new_upstream)}... ")
self._git.checkout(new_upstream)
print(green_ok())
elif new_downstreams:
# If no upstream and there are downstreams, check out the first downstream
print_no_newline(f"Checking out {bold(new_downstreams[0])}... ")
self._git.checkout(new_downstreams[0])
print(green_ok())
# Otherwise, stay on the current (slid-out) branch

# Only perform rebase/merge if there is a new upstream
Expand All @@ -112,7 +116,9 @@ def slide_out(self,
use_merge = opt_merge or (anno and anno.qualifiers.update_with_merge)
use_rebase = not use_merge and (not anno or anno.qualifiers.rebase)
if use_merge or use_rebase:
print_no_newline(f"Checking out {bold(new_downstream)}... ")
self._git.checkout(new_downstream)
print(green_ok())
if use_merge:
print(f"Merging {bold(new_upstream)} into {bold(new_downstream)}...")
self._git.merge(
Expand Down
15 changes: 10 additions & 5 deletions git_machete/client/traverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from git_machete.git_operations import (GitContext, LocalBranchShortName,
SyncToRemoteStatus)
from git_machete.utils import (bold, flat_map, fmt, get_pretty_choices,
get_right_arrow, normalize_path_for_display,
get_right_arrow, green_ok,
normalize_path_for_display, print_no_newline,
warn)


Expand Down Expand Up @@ -143,15 +144,17 @@ def traverse(
if opt_start_from == TraverseStartFrom.ROOT:
dest = self.root_branch_for(self._git.get_current_branch(), if_unmanaged=PickRoot.FIRST)
self._print_new_line(False)
print(f"Checking out the root branch ({bold(dest)})")
print_no_newline(f"Checking out the root branch ({bold(dest)})... ")
self._switch_to_branch_worktree(dest)
print(green_ok())
current_branch = dest
elif opt_start_from == TraverseStartFrom.FIRST_ROOT:
# Note that we already ensured that there is at least one managed branch.
dest = self.managed_branches[0]
self._print_new_line(False)
print(f"Checking out the first root branch ({bold(dest)})")
print_no_newline(f"Checking out the first root branch ({bold(dest)})... ")
self._switch_to_branch_worktree(dest)
print(green_ok())
current_branch = dest
elif opt_start_from == TraverseStartFrom.HERE:
current_branch = self._git.get_current_branch()
Expand All @@ -160,8 +163,9 @@ def traverse(
dest = opt_start_from
self.expect_in_managed_branches(dest)
self._print_new_line(False)
print(f"Checking out branch {bold(dest)}")
print_no_newline(f"Checking out branch {bold(dest)}... ")
self._switch_to_branch_worktree(dest)
print(green_ok())
current_branch = dest
else:
raise UnexpectedMacheteException(f"Unexpected value for opt_start_from: {opt_start_from}")
Expand Down Expand Up @@ -237,8 +241,9 @@ def traverse(
needs_any_action = needs_slide_out or needs_parent_sync or needs_remote_sync or needs_retarget_pr or needs_create_pr
if branch != current_branch and needs_any_action:
self._print_new_line(False)
print(f"Checking out {bold(branch)}")
print_no_newline(f"Checking out {bold(branch)}... ")
self._switch_to_branch_worktree(branch)
print(green_ok())
current_branch = branch
self._print_new_line(False)
self.status(
Expand Down
52 changes: 25 additions & 27 deletions git_machete/client/with_code_hosting.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
RemoteBranchShortName,
SyncToRemoteStatus)
from git_machete.utils import (bold, colored_yes_no, debug, find_or_none, fmt,
get_pretty_choices, get_right_arrow, slurp_file,
warn)
get_pretty_choices, get_right_arrow, green_ok,
print_no_newline, slurp_file, warn)


class PRDescriptionIntroStyle(ParsableEnum):
Expand Down Expand Up @@ -53,9 +53,9 @@ def code_hosting_client(self, value: CodeHostingClient) -> None:
def _get_all_open_prs(self) -> List[PullRequest]:
if self.__all_open_prs is None:
spec = self.code_hosting_spec
print(f'Checking for open {spec.display_name} {spec.pr_short_name}s... ', end='', flush=True)
print_no_newline(f'Checking for open {spec.display_name} {spec.pr_short_name}s... ')
self.__all_open_prs = self.code_hosting_client.get_open_pull_requests()
print(fmt('<green><b>OK</b></green>'))
print(green_ok())
return self.__all_open_prs

def _pull_request_annotation(self, pr: PullRequest, current_user: Optional[str], *, include_url: bool = False) -> str:
Expand Down Expand Up @@ -272,27 +272,27 @@ def create_pull_request(

# Check both base and head branches in a single git ls-remote call if they use the same remote
if base_org_repo_remote.remote == head_org_repo_remote.remote:
print(f"Checking if {spec.head_branch_name} branch {bold(head)} "
f"exists in {bold(head_org_repo_remote.remote)} remote... ", end='', flush=True)
print_no_newline(f"Checking if {spec.head_branch_name} branch {bold(head)} "
f"exists in {bold(head_org_repo_remote.remote)} remote... ")

branches_existence = self._git.do_remote_branches_exist(base_org_repo_remote.remote, base, head)
base_branch_found_on_remote = branches_existence[base]
head_branch_found_on_remote = branches_existence[head]

print(fmt(colored_yes_no(head_branch_found_on_remote)))

print(f"Checking if {spec.base_branch_name} branch {bold(base)} "
f"exists in {bold(base_org_repo_remote.remote)} remote... ", end='', flush=True)
print_no_newline(f"Checking if {spec.base_branch_name} branch {bold(base)} "
f"exists in {bold(base_org_repo_remote.remote)} remote... ")
print(fmt(colored_yes_no(base_branch_found_on_remote)))
else:
# Different remotes, check separately (head first, then base)
print(f"Checking if {spec.head_branch_name} branch {bold(head)} "
f"exists in {bold(head_org_repo_remote.remote)} remote... ", end='', flush=True)
print_no_newline(f"Checking if {spec.head_branch_name} branch {bold(head)} "
f"exists in {bold(head_org_repo_remote.remote)} remote... ")
head_branch_found_on_remote = self._git.does_remote_branch_exist(head_org_repo_remote.remote, head)
print(fmt(colored_yes_no(head_branch_found_on_remote)))

print(f"Checking if {spec.base_branch_name} branch {bold(base)} "
f"exists in {bold(base_org_repo_remote.remote)} remote... ", end='', flush=True)
print_no_newline(f"Checking if {spec.base_branch_name} branch {bold(base)} "
f"exists in {bold(base_org_repo_remote.remote)} remote... ")
base_branch_found_on_remote = self._git.does_remote_branch_exist(base_org_repo_remote.remote, base)
print(fmt(colored_yes_no(base_branch_found_on_remote)))

Expand Down Expand Up @@ -361,15 +361,14 @@ def create_pull_request(
else:
description = self._git.get_commit_data(commits[0].hash, GitFormatPatterns.MESSAGE_BODY) if commits else ''

ok_str = '<green><b>OK</b></green>'
article = "a" if opt_draft else spec.pr_short_name_article
print(f'Creating {article} {"draft " if opt_draft else ""}{spec.pr_short_name} '
f'from {bold(head)} to {bold(base)}... ', end='', flush=True)
print_no_newline(f'Creating {article} {"draft " if opt_draft else ""}{spec.pr_short_name} '
f'from {bold(head)} to {bold(base)}... ')

pr: PullRequest = self.code_hosting_client.create_pull_request(
head=head, head_org_repo=head_org_repo, base=base,
title=title, description=description, draft=opt_draft)
print(fmt(f'{ok_str}, see `{pr.html_url}`'))
print(fmt(green_ok() + f', see `{pr.html_url}`'))

style = self.__get_pr_description_into_style_from_config()
# If base branch has NOT originally been found on the remote,
Expand All @@ -380,37 +379,36 @@ def create_pull_request(
# let's update the PR description after it's already created (so that we know the current PR's number).
new_description = self._get_updated_pull_request_description(pr)
if new_description.strip() != description.strip():
print(f'Updating description of {pr.display_text()} to include '
f'the chain of {spec.pr_short_name}s... ', end='', flush=True)
print_no_newline(f'Updating description of {pr.display_text()} to include '
f'the chain of {spec.pr_short_name}s... ')
self.code_hosting_client.set_description_of_pull_request(pr.number, new_description)
print(fmt(ok_str))
print(green_ok())

milestone_path: str = self._git.get_main_worktree_git_subpath('info', 'milestone')
if os.path.isfile(milestone_path):
milestone = slurp_file(milestone_path).strip()
else:
milestone = None
if milestone:
print(f'Setting milestone of {pr.display_text()} to {bold(milestone)}... ', end='', flush=True)
print_no_newline(f'Setting milestone of {pr.display_text()} to {bold(milestone)}... ')
self.code_hosting_client.set_milestone_of_pull_request(pr.number, milestone=milestone)
print(fmt(ok_str))
print(green_ok())

if current_user:
print(f'Adding {bold(current_user)} as assignee to {pr.display_text()}... ', end='', flush=True)
print_no_newline(f'Adding {bold(current_user)} as assignee to {pr.display_text()}... ')
self.code_hosting_client.add_assignees_to_pull_request(pr.number, [current_user])
print(fmt(ok_str))
print(green_ok())

reviewers_path = self._git.get_main_worktree_git_subpath('info', 'reviewers')
if os.path.isfile(reviewers_path):
reviewers = utils.get_non_empty_lines(slurp_file(reviewers_path))
else:
reviewers = []
if reviewers:
print(f'Adding {", ".join(bold(reviewer) for reviewer in reviewers)} '
f'as reviewer{"s" if len(reviewers) > 1 else ""} to {pr.display_text()}... ',
end='', flush=True)
print_no_newline(f'Adding {", ".join(bold(reviewer) for reviewer in reviewers)} '
f'as reviewer{"s" if len(reviewers) > 1 else ""} to {pr.display_text()}... ')
self.code_hosting_client.add_reviewers_to_pull_request(pr.number, reviewers)
print(fmt(ok_str))
print(green_ok())

self._state.annotations[head] = Annotation(self._pull_request_annotation(pr, current_user), qualifiers=Qualifiers())
self.save_branch_layout_file()
Expand Down
8 changes: 8 additions & 0 deletions git_machete/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ def warn(msg: str, *, apply_fmt: bool = True, end: str = '\n') -> None:
displayed_warnings.add(msg)


def print_no_newline(msg: str) -> None:
print(msg, end='', flush=True)


def green_ok() -> str:
return fmt('<green><b>OK</b></green>')


def slurp_file(path: str) -> str:
with open(path, 'r') as file:
return file.read()
Expand Down
1 change: 1 addition & 0 deletions tests/test_go.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def test_go_up(self) -> None:
["g", "u"],
"Warn: branch level-2-branch not found in the tree of branch dependencies; "
"the upstream has been inferred to level-1-branch\n"
"Checking out level-1-branch... OK\n"
)
assert 'level-1-branch' == launch_command("show", "current").strip()

Expand Down
1 change: 1 addition & 0 deletions tests/test_slide_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def test_slide_out(self, mocker: MockerFixture) -> None:
self.patch_symbol(mocker, 'builtins.input', mock_input_returning_y)
assert_success(
["slide-out", "-n", "--delete"],
"Checking out child_b... OK\n"
"Delete branch child_d (unmerged to HEAD)? (y, N, q)\n"
)
assert "child_d" not in get_local_branches()
Expand Down
Loading