Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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.45.1

- added: `advice.macheteCreateFromFork` git config key suppresses the fork warning in `github create-pr` and `gitlab create-mr` when set to `false`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR looks okay! pls rebase & resolve the conflict


## New in git-machete 3.45.0

- added: `GIT_MACHETE_PUSH_OPTS` environment variable forwards arbitrary extra options to every `git push` invocation (contributed by @HWiese1980)
Expand Down
12 changes: 12 additions & 0 deletions docs/man/git-machete.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions docs/source/cli/github.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ Create, check out and manage GitHub PRs while keeping them reflected in branch l

**Git config keys**

``advice.macheteCreateFromFork`` (``create-pr`` only)
.. include:: git-config-keys/advice.macheteCreateFromFork.rst

``machete.github.{domain,remote,organization,repository,baseRemote,baseOrganization,baseRepository}`` (all subcommands)
.. include:: git-config-keys/github.access.rst

Expand Down
3 changes: 3 additions & 0 deletions docs/source/cli/gitlab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ Create, check out and manage GitLab MRs while keeping them reflected in branch l

**Git config keys**

``advice.macheteCreateFromFork`` (``create-mr`` only)
.. include:: git-config-keys/advice.macheteCreateFromFork.rst

``machete.gitlab.{domain,remote,namespace,project,baseRemote,baseNamespace,baseProject}`` (all subcommands)
.. include:: git-config-keys/gitlab.access.rst

Expand Down
4 changes: 4 additions & 0 deletions docs/source/git-config-keys/advice.macheteCreateFromFork.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Controls the warning shown when creating a pull/merge request whose base and head branches live in different repositories.
Set to ``false`` to suppress the warning about creating stacked pull/merge requests from forks; enabled by default.
This setting affects only the warning, not repository selection or request creation.
For example, run ``git config advice.macheteCreateFromFork false`` in a repository, or add ``--global`` to apply it everywhere.
2 changes: 1 addition & 1 deletion git_machete/client/with_code_hosting.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def create_pull_request(

base_org_repo = base_org_repo_remote.extract_org_and_repo()
head_org_repo = head_org_repo_remote.extract_org_and_repo()
if base_org_repo != head_org_repo:
if base_org_repo != head_org_repo and self._config.advice_machete_create_from_fork():
warn(f"{spec.base_branch_name} branch <b>{base}</b> lives in <b>{base_org_repo}</b> {spec.repository_name},\n"
f"while {spec.head_branch_name} branch <b>{head}</b> lives in <b>{head_org_repo}</b> {spec.repository_name}.\n"
f"git-machete will now attempt to create {spec.pr_short_name_article} {spec.pr_short_name} in <b>{base_org_repo}</b>.\n"
Expand Down
4 changes: 4 additions & 0 deletions git_machete/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class PRDescriptionIntroStyle(ParsableEnum):

class MacheteConfig:

_ADVICE_MACHETE_CREATE_FROM_FORK = 'advice.macheteCreateFromFork'
_ADVICE_MACHETE_EDITOR_SELECTION = 'advice.macheteEditorSelection'
_SQUASH_MERGE_DETECTION = 'machete.squashMergeDetection'
_STATUS_EXTRA_SPACE_BEFORE_BRANCH_NAME = 'machete.status.extraSpaceBeforeBranchName'
Expand All @@ -61,6 +62,9 @@ def __init__(self, git: Optional[Git] = None) -> None:
def advice_machete_editor_selection(self) -> bool:
return self._git.get_config_attr_or_none(self._ADVICE_MACHETE_EDITOR_SELECTION) != 'false'

def advice_machete_create_from_fork(self) -> bool:
return self._git.get_config_attr_or_none(self._ADVICE_MACHETE_CREATE_FROM_FORK) != 'false'

def core_editor(self) -> Optional[str]:
return self._git.get_config_attr_or_none("core.editor")

Expand Down
12 changes: 12 additions & 0 deletions git_machete/generated_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,12 @@

<b>Git config keys</b>

`advice.macheteCreateFromFork` (`create-pr` only)
Controls the warning shown when creating a pull/merge request whose base and head branches live in different repositories.
Set to `false` to suppress the warning about creating stacked pull/merge requests from forks; enabled by default.
This setting affects only the warning, not repository selection or request creation.
For example, run `git config advice.macheteCreateFromFork false` in a repository, or add `--global` to apply it everywhere.

`machete.github.{domain,remote,organization,repository,baseRemote,baseOrganization,baseRepository}` (all subcommands)
`machete.github.domain`
The domain of the GitHub API server, for use with GitHub Enterprise; otherwise inferred from the remote URL.
Expand Down Expand Up @@ -1069,6 +1075,12 @@

<b>Git config keys</b>

`advice.macheteCreateFromFork` (`create-mr` only)
Controls the warning shown when creating a pull/merge request whose base and head branches live in different repositories.
Set to `false` to suppress the warning about creating stacked pull/merge requests from forks; enabled by default.
This setting affects only the warning, not repository selection or request creation.
For example, run `git config advice.macheteCreateFromFork false` in a repository, or add `--global` to apply it everywhere.

`machete.gitlab.{domain,remote,namespace,project,baseRemote,baseNamespace,baseProject}` (all subcommands)
`machete.gitlab.domain`
The domain of the GitLab API server, for use with a GitLab self-managed instance; otherwise inferred from the remote URL.
Expand Down
57 changes: 57 additions & 0 deletions tests/test_fork_advice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from typing import Optional

import pytest
from pytest_mock import MockerFixture

from tests import mockers_github, mockers_gitlab
from tests.base_test import BaseTest
from tests.cli_runner import assert_success, rewrite_branch_layout_file
from tests.git_repository import add_remote, commit, create_repo, create_repo_with_remote, new_branch, push, set_git_config_key
from tests.mockers_code_hosting import mock_from_url


class TestForkAdvice(BaseTest):

@pytest.mark.parametrize('provider', ['github', 'gitlab'])
@pytest.mark.parametrize('advice', [None, 'true', 'false'])
def test_create_from_fork(self, mocker: MockerFixture, provider: str, advice: Optional[str]) -> None:
self.patch_symbol(mocker, 'git_machete.code_hosting.OrganizationAndRepository.from_url', mock_from_url)
if provider == 'github':
self.patch_symbol(mocker, 'git_machete.github.GitHubToken.for_domain', mockers_github.mock_github_token_for_domain_none)
self.patch_symbol(mocker, 'urllib.request.urlopen', mockers_github.mock_urlopen(mockers_github.MockGitHubAPIState.with_prs()))
display, short, base_label, head_label, repository = 'GitHub', 'PR', 'base', 'head', 'repository'
else:
self.patch_symbol(mocker, 'git_machete.gitlab.GitLabToken.for_domain', mockers_gitlab.mock_gitlab_token_for_domain_none)
self.patch_symbol(mocker, 'urllib.request.urlopen', mockers_gitlab.mock_urlopen(mockers_gitlab.MockGitLabAPIState.with_mrs()))
display, short, base_label, head_label, repository = 'GitLab', 'MR', 'target', 'source', 'project'
article = 'a' if provider == 'github' else 'an'
create_repo_with_remote()
fork_path = create_repo('remote-1', bare=True, switch_dir_to_new_repo=False)
add_remote('fork', fork_path)
new_branch('master')
commit()
push(remote='fork', set_upstream=False)
push(remote='origin')
new_branch('feature')
commit()
push(remote='origin')
rewrite_branch_layout_file('master\n\tfeature')
set_git_config_key(f'machete.{provider}.baseRemote', 'fork')
if advice is not None:
set_git_config_key('advice.macheteCreateFromFork', advice)
warning = f"""
Warn: {base_label} branch master lives in example-org/example-repo-1 {repository},
while {head_label} branch feature lives in example-org/example-repo {repository}.
git-machete will now attempt to create {article} {short} in example-org/example-repo-1.

Note that due to the limitations of {display}'s {short} model, it is not possible to cleanly create stacked {short}s from forks.
For example, in a hypothetical chain some-other-branch -> feature -> master, {article} {short} from some-other-branch to feature
could not be created in example-org/example-repo-1, since its {head_label} branch feature lives in example-org/example-repo.
Generally, {short}s need to be created in whatever {repository} the {base_label} branch lives.
""" if advice != 'false' else ''
expected = warning + f"""
Checking if {head_label} branch feature exists in origin remote... YES
Checking if {base_label} branch master exists in fork remote... YES
Creating {article} {short} from feature to master... OK, see www.{provider}.com
"""
assert_success([provider, f'create-{short.lower()}'], expected)