def test_git_post_pull(): extras = { 'hooks': ['pull'], 'hooks_uri': 'fake_hook_uri', } with mock_hook_response(status=1, output='foo'): assert hooks.git_post_pull(extras) == hooks.HookResponse(1, 'foo')
def test_git_post_pull_exception_is_caught(): extras = { 'hooks': ['pull'], 'hooks_uri': 'fake_hook_uri', } with mock_hook_response(status=2, exception='Exception', exception_args=('foo',)): assert hooks.git_post_pull(extras).status == 128
def test_git_post_pull_exception_is_caught(): extras = { 'hooks': ['pull'], 'hooks_uri': 'fake_hook_uri', } with mock_hook_response(status=2, exception='Exception', exception_args=('foo', )): assert hooks.git_post_pull(extras).status == 128
def test_git_post_pull_is_disabled(): assert (hooks.git_post_pull({'hooks': ['push']}) == hooks.HookResponse(0, ''))
def backend(self, request, environ): """ WSGI Response producer for HTTP POST Git Smart HTTP requests. Reads commands and data from HTTP POST's body. returns an iterator obj with contents of git command's response to stdout """ # TODO(skreft): think how we could detect an HTTPLockedException, as # we probably want to have the same mechanism used by mercurial and # simplevcs. # For that we would need to parse the output of the command looking for # some signs of the HTTPLockedError, parse the data and reraise it in # pygrack. However, that would interfere with the streaming. # # Now the output of a blocked push is: # Pushing to http://test_regular:[email protected]:5001/vcs_test_git # POST git-receive-pack (1047 bytes) # remote: ERROR: Repository `vcs_test_git` locked by user `test_admin`. Reason:`lock_auto` # To http://test_regular:[email protected]:5001/vcs_test_git # ! [remote rejected] master -> master (pre-receive hook declined) # error: failed to push some refs to 'http://*****:*****@127.0.0.1:5001/vcs_test_git' git_command = self._get_fixedpath(request.path_info) if git_command not in self.commands: log.debug('command %s not allowed', git_command) return exc.HTTPForbidden() capabilities = None if git_command == 'git-upload-pack': capabilities = self._get_want_capabilities(request) if 'CONTENT_LENGTH' in environ: inputstream = FileWrapper(request.body_file_seekable, request.content_length) else: inputstream = request.body_file_seekable resp = Response() resp.content_type = ('application/x-%s-result' % git_command.encode('utf8')) resp.charset = None pre_pull_messages = '' if git_command == 'git-upload-pack': status, pre_pull_messages = hooks.git_pre_pull(self.extras) if status != 0: resp.app_iter = self._build_failed_pre_pull_response( capabilities, pre_pull_messages) return resp gitenv = dict(os.environ) # forget all configs gitenv['GIT_CONFIG_NOGLOBAL'] = '1' gitenv['RC_SCM_DATA'] = json.dumps(self.extras) cmd = [ self.git_path, git_command[4:], '--stateless-rpc', self.content_path ] log.debug('handling cmd %s', cmd) out = subprocessio.SubprocessIOChunker(cmd, inputstream=inputstream, env=gitenv, cwd=self.content_path, shell=False, fail_on_stderr=False, fail_on_return_code=False) if self.update_server_info and git_command == 'git-receive-pack': # We need to fully consume the iterator here, as the # update-server-info command needs to be run after the push. out = list(out) # Updating refs manually after each push. # This is required as some clients are exposing Git repos internally # with the dumb protocol. cmd = [self.git_path, 'update-server-info'] log.debug('handling cmd %s', cmd) output = subprocessio.SubprocessIOChunker( cmd, inputstream=inputstream, env=gitenv, cwd=self.content_path, shell=False, fail_on_stderr=False, fail_on_return_code=False) # Consume all the output so the subprocess finishes for _ in output: pass if git_command == 'git-upload-pack': unused_status, post_pull_messages = hooks.git_post_pull( self.extras) resp.app_iter = self._inject_messages_to_response( out, capabilities, pre_pull_messages, post_pull_messages) else: resp.app_iter = out return resp
def test_git_post_pull_is_disabled(): assert ( hooks.git_post_pull({'hooks': ['push']}) == hooks.HookResponse(0, ''))
def backend(self, request, environ): """ WSGI Response producer for HTTP POST Git Smart HTTP requests. Reads commands and data from HTTP POST's body. returns an iterator obj with contents of git command's response to stdout """ # TODO(skreft): think how we could detect an HTTPLockedException, as # we probably want to have the same mechanism used by mercurial and # simplevcs. # For that we would need to parse the output of the command looking for # some signs of the HTTPLockedError, parse the data and reraise it in # pygrack. However, that would interfere with the streaming. # # Now the output of a blocked push is: # Pushing to http://test_regular:[email protected]:5001/vcs_test_git # POST git-receive-pack (1047 bytes) # remote: ERROR: Repository `vcs_test_git` locked by user `test_admin`. Reason:`lock_auto` # To http://test_regular:[email protected]:5001/vcs_test_git # ! [remote rejected] master -> master (pre-receive hook declined) # error: failed to push some refs to 'http://*****:*****@127.0.0.1:5001/vcs_test_git' git_command = self._get_fixedpath(request.path_info) if git_command not in self.commands: log.debug('command %s not allowed', git_command) return exc.HTTPForbidden() capabilities = None if git_command == 'git-upload-pack': capabilities = self._get_want_capabilities(request) if 'CONTENT_LENGTH' in environ: inputstream = FileWrapper(request.body_file_seekable, request.content_length) else: inputstream = request.body_file_seekable resp = Response() resp.content_type = ('application/x-%s-result' % git_command.encode('utf8')) resp.charset = None if git_command == 'git-upload-pack': status, pre_pull_messages = hooks.git_pre_pull(self.extras) if status != 0: resp.app_iter = self._build_failed_pre_pull_response( capabilities, pre_pull_messages) return resp gitenv = dict(os.environ) # forget all configs gitenv['GIT_CONFIG_NOGLOBAL'] = '1' gitenv['RC_SCM_DATA'] = json.dumps(self.extras) cmd = [self.git_path, git_command[4:], '--stateless-rpc', self.content_path] log.debug('handling cmd %s', cmd) out = subprocessio.SubprocessIOChunker( cmd, inputstream=inputstream, env=gitenv, cwd=self.content_path, shell=False, fail_on_stderr=False, fail_on_return_code=False ) if self.update_server_info and git_command == 'git-receive-pack': # We need to fully consume the iterator here, as the # update-server-info command needs to be run after the push. out = list(out) # Updating refs manually after each push. # This is required as some clients are exposing Git repos internally # with the dumb protocol. cmd = [self.git_path, 'update-server-info'] log.debug('handling cmd %s', cmd) output = subprocessio.SubprocessIOChunker( cmd, inputstream=inputstream, env=gitenv, cwd=self.content_path, shell=False, fail_on_stderr=False, fail_on_return_code=False ) # Consume all the output so the subprocess finishes for _ in output: pass if git_command == 'git-upload-pack': out = list(out) unused_status, post_pull_messages = hooks.git_post_pull(self.extras) resp.app_iter = self._inject_messages_to_response( out, capabilities, pre_pull_messages, post_pull_messages) else: resp.app_iter = out return resp