Dulwich.io dulwich / e2735e8
post-receive hook (#743) Add support for running post-receive hook. battlmonstr authored 5 months ago GitHub committed 5 months ago
3 changed file(s) with 56 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
159159
160160 ShellHook.__init__(self, 'commit-msg', filepath, 1,
161161 prepare_msg, clean_msg, controldir)
162
163
164 class PostReceiveShellHook(ShellHook):
165 """post-receive shell hook"""
166
167 def __init__(self, controldir):
168 self.controldir = controldir
169 filepath = os.path.join(controldir, 'hooks', 'post-receive')
170 ShellHook.__init__(self, 'post-receive', filepath, 0)
171
172 def execute(self, client_refs):
173 # do nothing if the script doesn't exist
174 if not os.path.exists(self.filepath):
175 return None
176
177 try:
178 env = os.environ.copy()
179 env['GIT_DIR'] = self.controldir
180
181 p = subprocess.Popen(
182 self.filepath,
183 stdin=subprocess.PIPE,
184 stdout=subprocess.PIPE,
185 stderr=subprocess.PIPE,
186 env=env
187 )
188
189 # client_refs is a list of (oldsha, newsha, ref)
190 in_data = '\n'.join([' '.join(ref) for ref in client_refs])
191
192 out_data, err_data = p.communicate(in_data)
193
194 if (p.returncode != 0) or err_data:
195 err_fmt = "post-receive exit code: %d\n" \
196 + "stdout:\n%s\nstderr:\n%s"
197 err_msg = err_fmt % (p.returncode, out_data, err_data)
198 raise HookError(err_msg)
199 return out_data
200 except OSError as err:
201 raise HookError(repr(err))
6969 PreCommitShellHook,
7070 PostCommitShellHook,
7171 CommitMsgShellHook,
72 PostReceiveShellHook,
7273 )
7374
7475 from dulwich.line_ending import BlobNormalizer
954955 self.hooks['pre-commit'] = PreCommitShellHook(self.controldir())
955956 self.hooks['commit-msg'] = CommitMsgShellHook(self.controldir())
956957 self.hooks['post-commit'] = PostCommitShellHook(self.controldir())
958 self.hooks['post-receive'] = PostReceiveShellHook(self.controldir())
957959
958960 def _write_reflog(self, ref, old_sha, new_sha, committer, timestamp,
959961 timezone, message):
5858 ApplyDeltaError,
5959 ChecksumMismatch,
6060 GitProtocolError,
61 HookError,
6162 NotGitRepository,
6263 UnexpectedCommandError,
6364 ObjectFormatException,
980981 write(None)
981982 flush()
982983
984 def _on_post_receive(self, client_refs):
985 hook = self.repo.hooks.get('post-receive', None)
986 if not hook:
987 return
988 try:
989 output = hook.execute(client_refs)
990 if output:
991 self.proto.write_sideband(SIDE_BAND_CHANNEL_PROGRESS, output)
992 except HookError as err:
993 self.proto.write_sideband(SIDE_BAND_CHANNEL_FATAL, repr(err))
994
983995 def handle(self):
984996 if self.advertise_refs or not self.http_req:
985997 refs = sorted(self.repo.get_refs().items())
10161028
10171029 # backend can now deal with this refs and read a pack using self.read
10181030 status = self._apply_pack(client_refs)
1031
1032 self._on_post_receive(client_refs)
10191033
10201034 # when we have read all the pack from the client, send a status report
10211035 # if the client asked for it