diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2015-01-12 14:55:31 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2015-01-12 14:55:31 +0100 |
commit | e8eae18dcc360e6ab96c2291982bd4306adc01b9 (patch) | |
tree | 804cc52c1a9976a7274000d9a446bae2b4f032b3 /git/index | |
parent | e7671110bc865786ffe61cf9b92bf43c03759229 (diff) | |
download | gitpython-e8eae18dcc360e6ab96c2291982bd4306adc01b9.tar.gz |
IndexFile.commit() now runs pre-commit and post-commit hooks.
However, it does so only on posix. The test-case will run on posix only
as well.
Please note that in theory, even on windows we will attempt to run hooks,
even though I am not sure that this will actually work.
Fixes #81
Diffstat (limited to 'git/index')
-rw-r--r-- | git/index/base.py | 8 | ||||
-rw-r--r-- | git/index/fun.py | 47 |
2 files changed, 50 insertions, 5 deletions
diff --git a/git/index/base.py b/git/index/base.py index db0c3cda..7002385c 100644 --- a/git/index/base.py +++ b/git/index/base.py @@ -63,7 +63,8 @@ from .fun import ( aggressive_tree_merge, write_tree_from_cache, stat_mode_to_index_mode, - S_IFGITLINK + S_IFGITLINK, + run_commit_hook ) from gitdb.base import IStream @@ -893,9 +894,12 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): :note: If you have manually altered the .entries member of this instance, don't forget to write() your changes to disk beforehand. :return: Commit object representing the new commit""" + run_commit_hook('pre-commit', self) tree = self.write_tree() - return Commit.create_from_tree(self.repo, tree, message, parent_commits, + rval = Commit.create_from_tree(self.repo, tree, message, parent_commits, head, author=author, committer=committer) + run_commit_hook('post-commit', self) + return rval @classmethod def _flush_stdin_and_wait(cls, proc, ignore_stdout=False): diff --git a/git/index/fun.py b/git/index/fun.py index f0dee961..38ad843b 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -13,9 +13,14 @@ from stat import ( S_IFGITLINK = S_IFLNK | S_IFDIR # a submodule from io import BytesIO +import os +import subprocess from git.util import IndexFileSHA1Writer -from git.exc import UnmergedEntriesError +from git.exc import ( + UnmergedEntriesError, + HookExecutionError +) from git.objects.fun import ( tree_to_stream, traverse_tree_recursive, @@ -37,10 +42,46 @@ from .util import ( from gitdb.base import IStream from gitdb.typ import str_tree_type -from git.compat import defenc +from git.compat import ( + defenc, + force_text +) __all__ = ('write_cache', 'read_cache', 'write_tree_from_cache', 'entry_key', - 'stat_mode_to_index_mode', 'S_IFGITLINK') + 'stat_mode_to_index_mode', 'S_IFGITLINK', 'run_commit_hook', 'hook_path') + + +def hook_path(name, git_dir): + """:return: path to the given named hook in the given git repository directory""" + return os.path.join(git_dir, 'hooks', name) + + +def run_commit_hook(name, index): + """Run the commit hook of the given name. Silently ignores hooks that do not exist. + :param name: name of hook, like 'pre-commit' + :param index: IndexFile instance + :raises HookExecutionError: """ + hp = hook_path(name, index.repo.git_dir) + if not os.access(hp, os.X_OK): + return + + env = os.environ.copy() + env['GIT_INDEX_FILE'] = index.path + env['GIT_EDITOR'] = ':' + cmd = subprocess.Popen(hp, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=(os.name == 'posix')) + stdout, stderr = cmd.communicate() + cmd.stdout.close() + cmd.stderr.close() + + if cmd.returncode != 0: + stdout = force_text(stdout, defenc) + stderr = force_text(stderr, defenc) + raise HookExecutionError(hp, cmd.returncode, stdout, stderr) + # end handle return code def stat_mode_to_index_mode(mode): |