|
13 | 13 | S_IFGITLINK = S_IFLNK | S_IFDIR # a submodule
|
14 | 14 |
|
15 | 15 | from io import BytesIO
|
| 16 | +import os |
| 17 | +import subprocess |
16 | 18 |
|
17 | 19 | from git.util import IndexFileSHA1Writer
|
18 |
| -from git.exc import UnmergedEntriesError |
| 20 | +from git.exc import ( |
| 21 | + UnmergedEntriesError, |
| 22 | + HookExecutionError |
| 23 | +) |
19 | 24 | from git.objects.fun import (
|
20 | 25 | tree_to_stream,
|
21 | 26 | traverse_tree_recursive,
|
|
37 | 42 |
|
38 | 43 | from gitdb.base import IStream
|
39 | 44 | from gitdb.typ import str_tree_type
|
40 |
| -from git.compat import defenc |
| 45 | +from git.compat import ( |
| 46 | + defenc, |
| 47 | + force_text |
| 48 | +) |
41 | 49 |
|
42 | 50 | __all__ = ('write_cache', 'read_cache', 'write_tree_from_cache', 'entry_key',
|
43 |
| - 'stat_mode_to_index_mode', 'S_IFGITLINK') |
| 51 | + 'stat_mode_to_index_mode', 'S_IFGITLINK', 'run_commit_hook', 'hook_path') |
| 52 | + |
| 53 | + |
| 54 | +def hook_path(name, git_dir): |
| 55 | + """:return: path to the given named hook in the given git repository directory""" |
| 56 | + return os.path.join(git_dir, 'hooks', name) |
| 57 | + |
| 58 | + |
| 59 | +def run_commit_hook(name, index): |
| 60 | + """Run the commit hook of the given name. Silently ignores hooks that do not exist. |
| 61 | + :param name: name of hook, like 'pre-commit' |
| 62 | + :param index: IndexFile instance |
| 63 | + :raises HookExecutionError: """ |
| 64 | + hp = hook_path(name, index.repo.git_dir) |
| 65 | + if not os.access(hp, os.X_OK): |
| 66 | + return |
| 67 | + |
| 68 | + env = os.environ.copy() |
| 69 | + env['GIT_INDEX_FILE'] = index.path |
| 70 | + env['GIT_EDITOR'] = ':' |
| 71 | + cmd = subprocess.Popen(hp, |
| 72 | + env=env, |
| 73 | + stdout=subprocess.PIPE, |
| 74 | + stderr=subprocess.PIPE, |
| 75 | + close_fds=(os.name == 'posix')) |
| 76 | + stdout, stderr = cmd.communicate() |
| 77 | + cmd.stdout.close() |
| 78 | + cmd.stderr.close() |
| 79 | + |
| 80 | + if cmd.returncode != 0: |
| 81 | + stdout = force_text(stdout, defenc) |
| 82 | + stderr = force_text(stderr, defenc) |
| 83 | + raise HookExecutionError(hp, cmd.returncode, stdout, stderr) |
| 84 | + # end handle return code |
44 | 85 |
|
45 | 86 |
|
46 | 87 | def stat_mode_to_index_mode(mode):
|
|
0 commit comments