コード例 #1
0
ファイル: github.py プロジェクト: Polyconseil/trac-github
    def process_request(self, req):
        if req.method != 'POST':
            msg = u'Method not allowed (%s)\n' % req.method
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        if req.args.get('token') != self.token:
            msg = u'Invalid token (%s)\n' % req.args.get('token')
            req.send(msg.encode('utf-8'), 'text/plain', 403)

        path = req.args.get('path', '/')
        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        if self.autofetch:
            git = repos.git.repo
            output += u'* Running git fetch\n'
            output += git.fetch()
            output += u'* Updating references\n'
            remote_refs = git.for_each_ref(
                    "--format=%(refname)", "refs/remotes/origin").split()
            for remote_ref in remote_refs:
                local_ref = remote_ref.replace('remotes/origin', 'heads', 1)
                output += git.update_ref(local_ref, remote_ref)

        data = req.args.get('payload')
        if data:
            revs = [commit['id'] for commit in json.loads(data)['commits']]
            if revs:
                output += u'* Adding changesets %s\n' % u', '.join(revs)
                rm.notify('changeset_added', reponame, revs)

        req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
コード例 #2
0
class ChangesetIndexerEventsTestCase(BaseBloodhoundSearchTest):
    def setUp(self):
        super(ChangesetIndexerEventsTestCase, self).setUp()
        self.whoosh_backend = WhooshBackend(self.env)
        self.whoosh_backend.recreate_index()
        self.search_api = BloodhoundSearchApi(self.env)
        self.repository_manager = RepositoryManager(self.env)
        self.inject_dummy_repository()

    def test_can_index_added_changeset(self):
        rev = self.insert_changeset("Changed document 1.")

        results = self.search_api.query("*:*")

        self.assertEqual(1, results.hits)
        doc = results.docs[0]
        self.assertEqual('%s/dummy' % rev, doc["id"])
        self.assertEqual('dummy', doc["repository"])
        self.assertEqual('1', doc["revision"])
        self.assertEqual("Changed document 1.", doc["message"])

    def test_can_index_modified_changeset(self):
        rev = self.insert_changeset("Changed document 1.")
        self.modify_changeset(rev, "Added document 1.")

        results = self.search_api.query("*:*")

        self.assertEqual(1, results.hits)
        doc = results.docs[0]
        self.assertEqual('%s/dummy' % rev, doc["id"])
        self.assertEqual('dummy', doc["repository"])
        self.assertEqual('1', doc["revision"])
        self.assertEqual("Added document 1.", doc["message"])

    def insert_changeset(self, message, author=None, date=None, revision=None):
        rev = self.repository.add_changeset(revision, message, author, date)
        self.repository_manager.notify("changeset_added", 'dummy', [rev])
        return rev

    def modify_changeset(self, rev, message=None, author=None, date=None):
        changeset = self.repository.get_changeset(rev)
        if message is not None:
            changeset.message = message
        if author is not None:
            changeset.author = author
        if date is not None:
            changeset.date = date
        self.repository_manager.notify("changeset_modified", "dummy", [rev])

    def inject_dummy_repository(self):
        # pylint: disable=protected-access,attribute-defined-outside-init
        self.repository = DummyRepositry()
        self.repository_connector = DummyRepositoryConnector(self.env)
        self.repository_connector.repository = self.repository
        self.repository_manager._all_repositories = {
            'dummy': dict(dir='dirname', type='dummy')
        }
        self.repository_manager._connectors = {
            'dummy': (self.repository_connector, 100)
        }
コード例 #3
0
class ChangesetIndexerEventsTestCase(BaseBloodhoundSearchTest):
    def setUp(self):
        super(ChangesetIndexerEventsTestCase, self).setUp()
        self.whoosh_backend = WhooshBackend(self.env)
        self.whoosh_backend.recreate_index()
        self.search_api = BloodhoundSearchApi(self.env)
        self.repository_manager = RepositoryManager(self.env)
        self.inject_dummy_repository()

    def test_can_index_added_changeset(self):
        rev = self.insert_changeset("Changed document 1.")

        results = self.search_api.query("*:*")

        self.assertEqual(1, results.hits)
        doc = results.docs[0]
        self.assertEqual('%s/dummy' % rev, doc["id"])
        self.assertEqual('dummy', doc["repository"])
        self.assertEqual('1', doc["revision"])
        self.assertEqual("Changed document 1.", doc["message"])

    def test_can_index_modified_changeset(self):
        rev = self.insert_changeset("Changed document 1.")
        self.modify_changeset(rev, "Added document 1.")

        results = self.search_api.query("*:*")

        self.assertEqual(1, results.hits)
        doc = results.docs[0]
        self.assertEqual('%s/dummy' % rev, doc["id"])
        self.assertEqual('dummy', doc["repository"])
        self.assertEqual('1', doc["revision"])
        self.assertEqual("Added document 1.", doc["message"])

    def insert_changeset(self, message, author=None, date=None, revision=None):
        rev = self.repository.add_changeset(revision, message, author, date)
        self.repository_manager.notify("changeset_added", 'dummy', [rev])
        return rev

    def modify_changeset(self, rev, message=None, author=None, date=None):
        changeset = self.repository.get_changeset(rev)
        if message is not None:
            changeset.message = message
        if author is not None:
            changeset.author = author
        if date is not None:
            changeset.date = date
        self.repository_manager.notify("changeset_modified", "dummy", [rev])

    def inject_dummy_repository(self):
        # pylint: disable=protected-access,attribute-defined-outside-init
        self.repository = DummyRepositry()
        self.repository_connector = DummyRepositoryConnector(self.env)
        self.repository_connector.repository = self.repository
        self.repository_manager._all_repositories = {
            'dummy': dict(dir='dirname', type='dummy')}
        self.repository_manager._connectors = {
            'dummy': (self.repository_connector, 100)}
コード例 #4
0
    def process_request(self, req):
        if req.method != 'POST':
            msg = u'Method not allowed (%s)\n' % req.method
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        repos.git.repo.remote('update', '--prune')
        output += u'* Synchronizing with clone\n'
        repos.git.sync()

        try:
            payload = json.loads(req.args['payload'])
            revs = [
                commit['id'] for commit in payload['commits']
                if commit['distinct']
            ]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        branches = self.get_branches(reponame)
        added, skipped, unknown = classify_commits(revs, repos, branches)

        if added:
            output += u'* Adding %s\n' % describe_commits(added)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added)

        if skipped:
            output += u'* Skipping %s\n' % describe_commits(skipped)

        if unknown:
            output += u'* Unknown %s\n' % describe_commits(unknown)
            self.log.error(u'Payload contains unknown %s',
                           describe_commits(unknown))

        for line in output.splitlines():
            self.log.debug(line)

        req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
コード例 #5
0
ファイル: github.py プロジェクト: nuxwin/trac-github
    def process_request(self, req):
        if req.method != 'POST':
            msg = u'Method not allowed (%s)\n' % req.method
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        repos.git.repo.remote('update', '--prune')
        output += u'* Synchronizing with clone\n'
        repos.git.sync()

        try:
            payload = json.loads(req.args['payload'])
            revs = [commit['id']
                    for commit in payload['commits'] if commit['distinct']]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        branches = self.get_branches(reponame)
        added, skipped, unknown = classify_commits(revs, repos, branches)

        if added:
            output += u'* Adding %s\n' % describe_commits(added)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added)

        if skipped:
            output += u'* Skipping %s\n' % describe_commits(skipped)

        if unknown:
            output += u'* Unknown %s\n' % describe_commits(unknown)
            self.log.error(u'Payload contains unknown %s',
                    describe_commits(unknown))

        for line in output.splitlines():
            self.log.debug(line)

        req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
コード例 #6
0
ファイル: github.py プロジェクト: gijs/trac-github
    def process_request(self, req):
        if req.method != "POST":
            msg = u"Method not allowed (%s)\n" % req.method
            self.log.warning(msg.rstrip("\n"))
            req.send(msg.encode("utf-8"), "text/plain", 405)

        path = req.args["path"]

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if path != "/":
            msg = u"No such repository (%s)\n" % path
            self.log.warning(msg.rstrip("\n"))
            req.send(msg.encode("utf-8"), "text/plain", 400)

        output = u"Running hook on %s\n" % (reponame or "(default)")

        output += u"* Updating clone\n"
        output += repos.git.repo.remote("update", "--prune")

        try:
            payload = json.loads(req.args["payload"])
            revs = [commit["id"] for commit in payload["commits"] if commit["distinct"]]
        except (ValueError, KeyError):
            msg = u"Invalid payload\n"
            self.log.warning(msg.rstrip("\n"))
            req.send(msg.encode("utf-8"), "text/plain", 400)

        branches = self.get_branches(reponame)
        added_revs, skipped_revs = [], []
        for rev in revs:
            if rev_in_branches(repos.get_changeset(rev), branches):
                added_revs.append(rev)
            else:
                skipped_revs.append(rev)

        if added_revs:
            output += u"* Adding %s\n" % describe_commits(added_revs)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify("changeset_added", reponame, added_revs)

        if skipped_revs:
            output += u"* Skipping %s\n" % describe_commits(skipped_revs)

        for line in output.splitlines():
            self.log.debug(line)

        req.send(output.encode("utf-8"), "text/plain", 200 if output else 204)
コード例 #7
0
ファイル: github.py プロジェクト: folpindo/trac-github
    def process_request(self, req):
        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if repos is None or path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        if req.method != 'POST':
            msg = u'Endpoint is ready to accept GitHub notifications.\n'
            self.log.warning(u'Method not allowed (%s)' % req.method)
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        event = req.get_header('X-GitHub-Event')
        if event == 'ping':
            payload = json.loads(req.read())
            req.send(payload['zen'].encode('utf-8'), 'text/plain', 200)
        elif event != 'push':
            msg = u'Only ping and push are supported\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        try:
            git = repos.git.repo             # GitRepository
        except AttributeError:
            git = repos.repos.git.repo       # GitCachedRepository
        git.remote('update', '--prune')

        # Ensure that repos.get_changeset can find the new changesets.
        output += u'* Synchronizing with clone\n'
        repos.sync()

        try:
            payload = json.loads(req.read())
            revs = [commit['id']
                    for commit in payload['commits'] if commit['distinct']]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        branches = self.get_branches(reponame)
        added, skipped, unknown = classify_commits(revs, repos, branches)

        if added:
            output += u'* Adding %s\n' % describe_commits(added)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added)

        if skipped:
            output += u'* Skipping %s\n' % describe_commits(skipped)

        if unknown:
            output += u'* Unknown %s\n' % describe_commits(unknown)
            self.log.error(u'Payload contains unknown %s',
                    describe_commits(unknown))

        for line in output.splitlines():
            self.log.debug(line)

        req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
コード例 #8
0
ファイル: github.py プロジェクト: twisted-infra/trac-github
    def process_request(self, req):
        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if repos is None or path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        if req.method != 'POST':
            msg = u'Endpoint is ready to accept GitHub notifications.\n'
            self.log.warning(u'Method not allowed (%s)' % req.method)
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        event = req.get_header('X-GitHub-Event')
        if event == 'ping':
            payload = json.loads(req.read())
            req.send(payload['zen'].encode('utf-8'), 'text/plain', 200)
        elif event != 'push':
            msg = u'Only ping and push are supported\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        try:
            git = repos.git.repo  # GitRepository
        except AttributeError:
            git = repos.repos.git.repo  # GitCachedRepository
        git.remote('update', '--prune')

        # Ensure that repos.get_changeset can find the new changesets.
        output += u'* Synchronizing with clone\n'
        repos.sync()

        try:
            payload = json.loads(req.read())
            revs = [
                commit['id'] for commit in payload['commits']
                if commit['distinct']
            ]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        branches = self.get_branches(reponame)
        added, skipped, unknown = classify_commits(revs, repos, branches)

        if added:
            output += u'* Adding %s\n' % describe_commits(added)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added)

        if skipped:
            output += u'* Skipping %s\n' % describe_commits(skipped)

        if unknown:
            output += u'* Unknown %s\n' % describe_commits(unknown)
            self.log.error(u'Payload contains unknown %s',
                           describe_commits(unknown))

        for line in output.splitlines():
            self.log.debug(line)

        req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
コード例 #9
0
    def process_request(self, req):
        if req.method != 'POST':
            msg = u'Method not allowed (%s)\n' % req.method
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        key = 'branches' if is_default(reponame) else '%s.branches' % reponame
        branches = self.config.getlist('github', key, sep=' ')

        if path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        output += repos.git.repo.remote('update', '--prune')

        try:
            payload = json.loads(req.args['payload'])
            revs = [commit['id'] for commit in payload['commits']]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        if branches:
            added_revs, skipped_revs = [], []
            for rev in revs:
                if allow_revision(rev, repos, branches):
                    added_revs.append(rev)
                else:
                    skipped_revs.append(rev)
        else:
            added_revs, skipped_revs = revs, []

        if added_revs:
            if len(added_revs) == 1:
                output += u'* Adding commit %s\n' % added_revs[0]
            else:
                output += u'* Adding commits %s\n' % u', '.join(added_revs)

            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added_revs)

        if skipped_revs:
            if len(skipped_revs) == 1:
                output += u'* Skipping commit %s\n' % skipped_revs[0]
            else:
                output += u'* Skipping commits %s\n' % u', '.join(skipped_revs)

        for line in output.splitlines():
            self.log.debug(line)

        req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
コード例 #10
0
ファイル: __init__.py プロジェクト: trac-hacks/trac-github
    def process_request(self, req):
        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if repos is None or path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        if req.method != 'POST':
            msg = u'Endpoint is ready to accept GitHub notifications.\n'
            self.log.warning(u'Method not allowed (%s)', req.method)
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        # Verify the event's signature
        reqdata = req.read()
        signature = req.get_header('X-Hub-Signature')
        if not self._verify_webhook_signature(signature, reqdata):
            msg = u'Webhook signature verification failed\n'
            self.log.warning(msg.rstrip('\n')) # pylint: disable=no-member
            req.send(msg.encode('utf-8'), 'text/plain', 403)

        event = req.get_header('X-GitHub-Event')
        if event == 'ping':
            payload = json.loads(reqdata)
            req.send(payload['zen'].encode('utf-8'), 'text/plain', 200)
        elif event != 'push':
            msg = u'Only ping and push are supported\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        try:
            git = repos.git.repo             # GitRepository
        except AttributeError:
            git = repos.repos.git.repo       # GitCachedRepository
        git.remote('update', '--prune')

        # Ensure that repos.get_changeset can find the new changesets.
        output += u'* Synchronizing with clone\n'
        repos.sync()

        try:
            payload = json.loads(reqdata)
            revs = [commit['id']
                    for commit in payload['commits'] if commit['distinct']]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        branches = self.get_branches(reponame)
        added, skipped, unknown = classify_commits(revs, repos, branches)

        if added:
            output += u'* Adding %s\n' % describe_commits(added)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added)

        if skipped:
            output += u'* Skipping %s\n' % describe_commits(skipped)

        if unknown:
            output += u'* Unknown %s\n' % describe_commits(unknown)
            self.log.error(u'Payload contains unknown %s',
                    describe_commits(unknown))

        status = 200

        git_dir = git.rev_parse('--git-dir').rstrip('\n')
        hook = os.path.join(git_dir, 'hooks', 'trac-github-update')
        if os.path.isfile(hook):
            output += u'* Running trac-github-update hook\n'
            try:
                p = Popen(hook, cwd=git_dir,
                          stdin=PIPE, stdout=PIPE, stderr=STDOUT,
                          close_fds=trac.util.compat.close_fds)
            except Exception as e:
                output += u'Error: hook execution failed with exception\n%s' % (traceback.format_exc(),)
                status = 500
            else:
                hookoutput = p.communicate(input=reqdata)[0]
                output += hookoutput.decode('utf-8')
                if p.returncode != 0:
                    output += u'Error: hook failed with exit code %d\n' % (p.returncode,)
                    status = 500

        for line in output.splitlines():
            self.log.debug(line)

        if status == 200 and not output:
            status = 204

        req.send(output.encode('utf-8'), 'text/plain', status)
コード例 #11
0
ファイル: github.py プロジェクト: doytsujin/trac-github
    def process_request(self, req):
        path = req.args['path']

        rm = RepositoryManager(self.env)
        reponame, repos, path = rm.get_repository_by_path(path)

        if repos is None or path != '/':
            msg = u'No such repository (%s)\n' % path
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        if req.method != 'POST':
            msg = u'Endpoint is ready to accept GitHub notifications.\n'
            self.log.warning(u'Method not allowed (%s)', req.method)
            req.send(msg.encode('utf-8'), 'text/plain', 405)

        # Verify the event's signature
        reqdata = req.read()
        signature = req.get_header('X-Hub-Signature')
        if not self._verify_webhook_signature(signature, reqdata):
            msg = u'Webhook signature verification failed\n'
            self.log.warning(msg.rstrip('\n')) # pylint: disable=no-member
            req.send(msg.encode('utf-8'), 'text/plain', 403)

        event = req.get_header('X-GitHub-Event')
        if event == 'ping':
            payload = json.loads(reqdata)
            req.send(payload['zen'].encode('utf-8'), 'text/plain', 200)
        elif event != 'push':
            msg = u'Only ping and push are supported\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        output = u'Running hook on %s\n' % (reponame or '(default)')

        output += u'* Updating clone\n'
        try:
            git = repos.git.repo             # GitRepository
        except AttributeError:
            git = repos.repos.git.repo       # GitCachedRepository
        git.remote('update', '--prune')

        # Ensure that repos.get_changeset can find the new changesets.
        output += u'* Synchronizing with clone\n'
        repos.sync()

        try:
            payload = json.loads(reqdata)
            revs = [commit['id']
                    for commit in payload['commits'] if commit['distinct']]
        except (ValueError, KeyError):
            msg = u'Invalid payload\n'
            self.log.warning(msg.rstrip('\n'))
            req.send(msg.encode('utf-8'), 'text/plain', 400)

        branches = self.get_branches(reponame)
        added, skipped, unknown = classify_commits(revs, repos, branches)

        if added:
            output += u'* Adding %s\n' % describe_commits(added)
            # This is where Trac gets notified of the commits in the changeset
            rm.notify('changeset_added', reponame, added)

        if skipped:
            output += u'* Skipping %s\n' % describe_commits(skipped)

        if unknown:
            output += u'* Unknown %s\n' % describe_commits(unknown)
            self.log.error(u'Payload contains unknown %s',
                    describe_commits(unknown))

        status = 200

        git_dir = git.rev_parse('--git-dir').rstrip('\n')
        hook = os.path.join(git_dir, 'hooks', 'trac-github-update')
        if os.path.isfile(hook):
            output += u'* Running trac-github-update hook\n'
            try:
                p = Popen(hook, cwd=git_dir,
                          stdin=PIPE, stdout=PIPE, stderr=STDOUT,
                          close_fds=trac.util.compat.close_fds)
            except Exception as e:
                output += u'Error: hook execution failed with exception\n%s' % (traceback.format_exc(),)
                status = 500
            else:
                hookoutput = p.communicate(input=reqdata)[0]
                output += hookoutput.decode('utf-8')
                if p.returncode != 0:
                    output += u'Error: hook failed with exit code %d\n' % (p.returncode,)
                    status = 500

        for line in output.splitlines():
            self.log.debug(line)

        if status == 200 and not output:
            status = 204

        req.send(output.encode('utf-8'), 'text/plain', status)