Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: post-rewrite hook support #2036

Merged
merged 1 commit into from Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions pre_commit/commands/hook_impl.py
Expand Up @@ -78,6 +78,7 @@ def _ns(
commit_msg_filename: Optional[str] = None,
checkout_type: Optional[str] = None,
is_squash_merge: Optional[str] = None,
rewrite_command: Optional[str] = None,
) -> argparse.Namespace:
return argparse.Namespace(
color=color,
Expand All @@ -92,6 +93,7 @@ def _ns(
all_files=all_files,
checkout_type=checkout_type,
is_squash_merge=is_squash_merge,
rewrite_command=rewrite_command,
files=(),
hook=None,
verbose=False,
Expand Down Expand Up @@ -166,6 +168,7 @@ def _pre_push_ns(
'pre-commit': 0,
'pre-merge-commit': 0,
'post-merge': 1,
'post-rewrite': 1,
'pre-push': 2,
}

Expand Down Expand Up @@ -209,6 +212,8 @@ def _run_ns(
)
elif hook_type == 'post-merge':
return _ns(hook_type, color, is_squash_merge=args[0])
elif hook_type == 'post-rewrite':
return _ns(hook_type, color, rewrite_command=args[0])
else:
raise AssertionError(f'unexpected hook type: {hook_type}')

Expand Down
7 changes: 6 additions & 1 deletion pre_commit/commands/run.py
Expand Up @@ -245,7 +245,9 @@ def _compute_cols(hooks: Sequence[Hook]) -> int:

def _all_filenames(args: argparse.Namespace) -> Collection[str]:
# these hooks do not operate on files
if args.hook_stage in {'post-checkout', 'post-commit', 'post-merge'}:
if args.hook_stage in {
'post-checkout', 'post-commit', 'post-merge', 'post-rewrite',
}:
return ()
elif args.hook_stage in {'prepare-commit-msg', 'commit-msg'}:
return (args.commit_msg_filename,)
Expand Down Expand Up @@ -386,6 +388,9 @@ def run(
if args.is_squash_merge:
environ['PRE_COMMIT_IS_SQUASH_MERGE'] = args.is_squash_merge

if args.rewrite_command:
environ['PRE_COMMIT_REWRITE_COMMAND'] = args.rewrite_command

# Set pre_commit flag
environ['PRE_COMMIT'] = '1'

Expand Down
1 change: 1 addition & 0 deletions pre_commit/constants.py
Expand Up @@ -19,6 +19,7 @@
STAGES = (
'commit', 'merge-commit', 'prepare-commit-msg', 'commit-msg',
'post-commit', 'manual', 'post-checkout', 'push', 'post-merge',
'post-rewrite',
)

DEFAULT = 'default'
8 changes: 8 additions & 0 deletions pre_commit/main.py
Expand Up @@ -69,6 +69,7 @@ def _add_hook_type_option(parser: argparse.ArgumentParser) -> None:
'-t', '--hook-type', choices=(
'pre-commit', 'pre-merge-commit', 'pre-push', 'prepare-commit-msg',
'commit-msg', 'post-commit', 'post-checkout', 'post-merge',
'post-rewrite',
),
action=AppendReplaceDefault,
default=['pre-commit'],
Expand Down Expand Up @@ -146,6 +147,13 @@ def _add_run_options(parser: argparse.ArgumentParser) -> None:
'squash merge'
),
)
parser.add_argument(
'--rewrite-command',
help=(
'During a post-rewrite hook, specifies the command that invoked '
'the rewrite'
),
)


def _adjust_args_and_chdir(args: argparse.Namespace) -> None:
Expand Down
2 changes: 2 additions & 0 deletions testing/util.py
Expand Up @@ -72,6 +72,7 @@ def run_opts(
commit_msg_filename='',
checkout_type='',
is_squash_merge='',
rewrite_command='',
):
# These are mutually exclusive
assert not (all_files and files)
Expand All @@ -92,6 +93,7 @@ def run_opts(
commit_msg_filename=commit_msg_filename,
checkout_type=checkout_type,
is_squash_merge=is_squash_merge,
rewrite_command=rewrite_command,
)


Expand Down
9 changes: 9 additions & 0 deletions tests/commands/hook_impl_test.py
Expand Up @@ -99,6 +99,7 @@ def call(*_, **__):
('post-commit', []),
('post-merge', ['1']),
('post-checkout', ['old_head', 'new_head', '1']),
('post-rewrite', ['amend']),
# multiple choices for commit-editmsg
('prepare-commit-msg', ['.git/COMMIT_EDITMSG']),
('prepare-commit-msg', ['.git/COMMIT_EDITMSG', 'message']),
Expand Down Expand Up @@ -166,6 +167,14 @@ def test_run_ns_post_merge():
assert ns.is_squash_merge == '1'


def test_run_ns_post_rewrite():
ns = hook_impl._run_ns('post-rewrite', True, ('amend',), b'')
assert ns is not None
assert ns.hook_stage == 'post-rewrite'
assert ns.color is True
assert ns.rewrite_command == 'amend'


def test_run_ns_post_checkout():
ns = hook_impl._run_ns('post-checkout', True, ('a', 'b', 'c'), b'')
assert ns is not None
Expand Down
29 changes: 29 additions & 0 deletions tests/commands/install_uninstall_test.py
Expand Up @@ -817,6 +817,35 @@ def test_post_merge_integration(tempdir_factory, store):
assert os.path.exists('post-merge.tmp')


def test_post_rewrite_integration(tempdir_factory, store):
path = git_dir(tempdir_factory)
config = [
{
'repo': 'local',
'hooks': [{
'id': 'post-rewrite',
'name': 'Post rewrite',
'entry': 'touch post-rewrite.tmp',
'language': 'system',
'always_run': True,
'verbose': True,
'stages': ['post-rewrite'],
}],
},
]
write_config(path, config)
with cwd(path):
open('init', 'a').close()
cmd_output('git', 'add', '.')
install(C.CONFIG_FILE, store, hook_types=['post-rewrite'])
git_commit()

assert not os.path.exists('post-rewrite.tmp')

git_commit('--amend', '-m', 'ammended message')
assert os.path.exists('post-rewrite.tmp')


def test_post_checkout_integration(tempdir_factory, store):
path = git_dir(tempdir_factory)
config = [
Expand Down
9 changes: 9 additions & 0 deletions tests/commands/run_test.py
Expand Up @@ -504,6 +504,15 @@ def test_is_squash_merge(cap_out, store, repo_with_passing_hook):
assert environ['PRE_COMMIT_IS_SQUASH_MERGE'] == '1'


def test_rewrite_command(cap_out, store, repo_with_passing_hook):
args = run_opts(rewrite_command='amend')
environ: MutableMapping[str, str] = {}
ret, printed = _do_run(
cap_out, store, repo_with_passing_hook, args, environ,
)
assert environ['PRE_COMMIT_REWRITE_COMMAND'] == 'amend'


def test_checkout_type(cap_out, store, repo_with_passing_hook):
args = run_opts(from_ref='', to_ref='', checkout_type='1')
environ: MutableMapping[str, str] = {}
Expand Down
1 change: 1 addition & 0 deletions tests/repository_test.py
Expand Up @@ -1002,6 +1002,7 @@ def test_manifest_hooks(tempdir_factory, store):
stages=(
'commit', 'merge-commit', 'prepare-commit-msg', 'commit-msg',
'post-commit', 'manual', 'post-checkout', 'push', 'post-merge',
'post-rewrite',
),
types=['file'],
types_or=[],
Expand Down