Files
dvc/dvc/command/git_hook.py
T
2020-08-19 17:55:12 +03:00

160 lines
4.4 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()
def _run(self):
raise NotImplementedError
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"])
class CmdMergeDriver(CmdHookBase):
def _run(self):
from dvc.dvcfile import Dvcfile
from dvc.repo import Repo
dvc = Repo()
try:
with dvc.state:
ancestor = Dvcfile(dvc, self.args.ancestor, verify=False)
our = Dvcfile(dvc, self.args.our, verify=False)
their = Dvcfile(dvc, self.args.their, verify=False)
our.merge(ancestor, their)
return 0
finally:
dvc.close()
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)
MERGE_DRIVER_HELP = "Run GIT merge driver."
merge_driver_parser = git_hook_subparsers.add_parser(
"merge-driver",
parents=[parent_parser],
description=MERGE_DRIVER_HELP,
help=MERGE_DRIVER_HELP,
)
merge_driver_parser.add_argument(
"--ancestor",
required=True,
help="Ancestor's version of the conflicting file.",
)
merge_driver_parser.add_argument(
"--our",
required=True,
help="Current version of the conflicting file.",
)
merge_driver_parser.add_argument(
"--their",
required=True,
help="Other branch's version of the conflicting file.",
)
merge_driver_parser.set_defaults(func=CmdMergeDriver)