gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / dulwich / hooks.py @ 959
History | View | Annotate | Download (5.04 KB)
1 |
# hooks.py -- for dealing with git hooks
|
---|---|
2 |
# Copyright (C) 2012-2013 Jelmer Vernooij and others.
|
3 |
#
|
4 |
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
|
5 |
# General Public License as public by the Free Software Foundation; version 2.0
|
6 |
# or (at your option) any later version. You can redistribute it and/or
|
7 |
# modify it under the terms of either of these two licenses.
|
8 |
#
|
9 |
# Unless required by applicable law or agreed to in writing, software
|
10 |
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
# See the License for the specific language governing permissions and
|
13 |
# limitations under the License.
|
14 |
#
|
15 |
# You should have received a copy of the licenses; if not, see
|
16 |
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
|
17 |
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
|
18 |
# License, Version 2.0.
|
19 |
#
|
20 |
|
21 |
"""Access to hooks."""
|
22 |
|
23 |
import os |
24 |
import subprocess |
25 |
import sys |
26 |
import tempfile |
27 |
|
28 |
from dulwich.errors import ( |
29 |
HookError, |
30 |
) |
31 |
|
32 |
|
33 |
class Hook(object): |
34 |
"""Generic hook object."""
|
35 |
|
36 |
def execute(self, *args): |
37 |
"""Execute the hook with the given args
|
38 |
|
39 |
:param args: argument list to hook
|
40 |
:raise HookError: hook execution failure
|
41 |
:return: a hook may return a useful value
|
42 |
"""
|
43 |
raise NotImplementedError(self.execute) |
44 |
|
45 |
|
46 |
class ShellHook(Hook): |
47 |
"""Hook by executable file
|
48 |
|
49 |
Implements standard githooks(5) [0]:
|
50 |
|
51 |
[0] http://www.kernel.org/pub/software/scm/git/docs/githooks.html
|
52 |
"""
|
53 |
|
54 |
def __init__(self, name, path, numparam, |
55 |
pre_exec_callback=None, post_exec_callback=None): |
56 |
"""Setup shell hook definition
|
57 |
|
58 |
:param name: name of hook for error messages
|
59 |
:param path: absolute path to executable file
|
60 |
:param numparam: number of requirements parameters
|
61 |
:param pre_exec_callback: closure for setup before execution
|
62 |
Defaults to None. Takes in the variable argument list from the
|
63 |
execute functions and returns a modified argument list for the
|
64 |
shell hook.
|
65 |
:param post_exec_callback: closure for cleanup after execution
|
66 |
Defaults to None. Takes in a boolean for hook success and the
|
67 |
modified argument list and returns the final hook return value
|
68 |
if applicable
|
69 |
"""
|
70 |
self.name = name
|
71 |
self.filepath = path
|
72 |
self.numparam = numparam
|
73 |
|
74 |
self.pre_exec_callback = pre_exec_callback
|
75 |
self.post_exec_callback = post_exec_callback
|
76 |
|
77 |
if sys.version_info[0] == 2 and sys.platform == 'win32': |
78 |
# Python 2 on windows does not support unicode file paths
|
79 |
# http://bugs.python.org/issue1759845
|
80 |
self.filepath = self.filepath.encode(sys.getfilesystemencoding()) |
81 |
|
82 |
def execute(self, *args): |
83 |
"""Execute the hook with given args"""
|
84 |
|
85 |
if len(args) != self.numparam: |
86 |
raise HookError("Hook %s executed with wrong number of args. \ |
87 |
Expected %d. Saw %d. args: %s"
|
88 |
% (self.name, self.numparam, len(args), args)) |
89 |
|
90 |
if (self.pre_exec_callback is not None): |
91 |
args = self.pre_exec_callback(*args)
|
92 |
|
93 |
try:
|
94 |
ret = subprocess.call([self.filepath] + list(args)) |
95 |
if ret != 0: |
96 |
if (self.post_exec_callback is not None): |
97 |
self.post_exec_callback(0, *args) |
98 |
raise HookError("Hook %s exited with non-zero status" |
99 |
% (self.name))
|
100 |
if (self.post_exec_callback is not None): |
101 |
return self.post_exec_callback(1, *args) |
102 |
except OSError: # no file. silent failure. |
103 |
if (self.post_exec_callback is not None): |
104 |
self.post_exec_callback(0, *args) |
105 |
|
106 |
|
107 |
class PreCommitShellHook(ShellHook): |
108 |
"""pre-commit shell hook"""
|
109 |
|
110 |
def __init__(self, controldir): |
111 |
filepath = os.path.join(controldir, 'hooks', 'pre-commit') |
112 |
|
113 |
ShellHook.__init__(self, 'pre-commit', filepath, 0) |
114 |
|
115 |
|
116 |
class PostCommitShellHook(ShellHook): |
117 |
"""post-commit shell hook"""
|
118 |
|
119 |
def __init__(self, controldir): |
120 |
filepath = os.path.join(controldir, 'hooks', 'post-commit') |
121 |
|
122 |
ShellHook.__init__(self, 'post-commit', filepath, 0) |
123 |
|
124 |
|
125 |
class CommitMsgShellHook(ShellHook): |
126 |
"""commit-msg shell hook
|
127 |
|
128 |
:param args[0]: commit message
|
129 |
:return: new commit message or None
|
130 |
"""
|
131 |
|
132 |
def __init__(self, controldir): |
133 |
filepath = os.path.join(controldir, 'hooks', 'commit-msg') |
134 |
|
135 |
def prepare_msg(*args): |
136 |
(fd, path) = tempfile.mkstemp() |
137 |
|
138 |
with os.fdopen(fd, 'wb') as f: |
139 |
f.write(args[0])
|
140 |
|
141 |
return (path,)
|
142 |
|
143 |
def clean_msg(success, *args): |
144 |
if success:
|
145 |
with open(args[0], 'rb') as f: |
146 |
new_msg = f.read() |
147 |
os.unlink(args[0])
|
148 |
return new_msg
|
149 |
os.unlink(args[0])
|
150 |
|
151 |
ShellHook.__init__(self, 'commit-msg', filepath, 1, |
152 |
prepare_msg, clean_msg) |