Files
dvc/dvc/command/git_hook.py
T
c4164b3497 Use pre-commit for Git hooks (#3406)
* Initial design of using pre-commit for Git hooks

* Refactor to reuse existing code and provide merge capabilities

* Linter fixes

* More cleanup

* scm: make use_precommit_tool optional

* dvc: install our own hooks

* install: fix typo

* install: fix bugs in pre-commit integration

* install: don't forget 'always_run' for post-checkout

* install: no need to run pre-commit install if conf file doesn't exist

* install: fix bugs

* install: use python hooks

* add .pre-commit-hooks.yaml

Co-authored-by: Andrew Hare <[email protected]>
Co-authored-by: Ruslan Kuprieiev <[email protected]>
2020-03-16 20:34:01 +02:00

113 lines
3.1 KiB
Python

import logging
import os
from dvc.command.base import CmdBaseNoRepo, fix_subparsers
from dvc.exceptions import NotDvcRepoError
logger = logging.getLogger(__name__)
class CmdHookBase(CmdBaseNoRepo):
def run(self):
from dvc.repo import Repo
try:
repo = Repo()
repo.close()
except NotDvcRepoError:
return 0
return self._run()
class CmdPreCommit(CmdHookBase):
def _run(self):
from dvc.main import main
return main(["status"])
class CmdPostCheckout(CmdHookBase):
def run(self):
# when we are running from pre-commit tool, it doesn't provide CLI
# flags, but instead provides respective env vars that we could use.
flag = os.environ.get("PRE_COMMIT_CHECKOUT_TYPE")
if flag is None and len(self.args.args) >= 3:
# see https://git-scm.com/docs/githooks#_post_checkout
flag = self.args.args[2]
# checking out some reference and not specific file.
if flag != "1":
return 0
# make sure we are not in the middle of a rebase/merge, so we
# don't accidentally break it with an unsuccessful checkout.
# Note that git hooks are always running in repo root.
if os.path.isdir(os.path.join(".git", "rebase-merge")):
return 0
from dvc.main import main
return main(["checkout"])
class CmdPrePush(CmdHookBase):
def run(self):
from dvc.main import main
return main(["push"])
def add_parser(subparsers, parent_parser):
GIT_HOOK_HELP = "Run GIT hook."
git_hook_parser = subparsers.add_parser(
"git-hook",
parents=[parent_parser],
description=GIT_HOOK_HELP,
add_help=False,
)
git_hook_subparsers = git_hook_parser.add_subparsers(
dest="cmd",
help="Use `dvc daemon CMD --help` for command-specific help.",
)
fix_subparsers(git_hook_subparsers)
PRE_COMMIT_HELP = "Run pre-commit GIT hook."
pre_commit_parser = git_hook_subparsers.add_parser(
"pre-commit",
parents=[parent_parser],
description=PRE_COMMIT_HELP,
help=PRE_COMMIT_HELP,
)
pre_commit_parser.add_argument(
"args", nargs="*", help="Arguments passed by GIT or pre-commit tool.",
)
pre_commit_parser.set_defaults(func=CmdPreCommit)
POST_CHECKOUT_HELP = "Run post-checkout GIT hook."
post_checkout_parser = git_hook_subparsers.add_parser(
"post-checkout",
parents=[parent_parser],
description=POST_CHECKOUT_HELP,
help=POST_CHECKOUT_HELP,
)
post_checkout_parser.add_argument(
"args", nargs="*", help="Arguments passed by GIT or pre-commit tool.",
)
post_checkout_parser.set_defaults(func=CmdPostCheckout)
PRE_PUSH_HELP = "Run pre-push GIT hook."
pre_push_parser = git_hook_subparsers.add_parser(
"pre-push",
parents=[parent_parser],
description=PRE_PUSH_HELP,
help=PRE_PUSH_HELP,
)
pre_push_parser.add_argument(
"args", nargs="*", help="Arguments passed by GIT or pre-commit tool.",
)
pre_push_parser.set_defaults(func=CmdPrePush)