Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/tools/server-side/svnpubsub/svnpubsub/server.py  view on Meta::CPAN

        obj = {'commit': {}}
        obj['commit'].update(self.__dict__)
        return json.dumps(obj)

    def render_log(self):
        try:
            paths_changed = " %d paths changed" % len(self.changed)
        except:
            paths_changed = ""
        return "%s:%s repo '%s' id '%s'%s" % (self.type,
                                  self.format,
                                  self.repository,
                                  self.id,
                                  paths_changed)


HEARTBEAT_TIME = 15

class Client(object):
    def __init__(self, pubsub, r, type, repository):
        self.pubsub = pubsub
        r.notifyFinish().addErrback(self.finished)
        self.r = r
        self.type = type
        self.repository = repository
        self.alive = True
        log.msg("OPEN: %s:%d (%d clients online)"% (r.getClientIP(), r.client.port, pubsub.cc()+1))

    def finished(self, reason):
        self.alive = False
        log.msg("CLOSE: %s:%d (%d clients online)"% (self.r.getClientIP(), self.r.client.port, self.pubsub.cc()))
        try:
            self.pubsub.remove(self)
        except ValueError:
            pass

    def interested_in(self, commit):
        if self.type and self.type != commit.type:
            return False

        if self.repository and self.repository != commit.repository:
            return False

        return True

    def notify(self, data):
        self.write(data)

    def start(self):
        self.write_start()
        reactor.callLater(HEARTBEAT_TIME, self.heartbeat, None)

    def heartbeat(self, args):
        if self.alive:
            self.write_heartbeat()
            reactor.callLater(HEARTBEAT_TIME, self.heartbeat, None)

    def write_data(self, data):
        self.write(data + "\n\0")

    """ "Data must not be unicode" is what the interfaces.ITransport says... grr. """
    def write(self, input):
        self.r.write(str(input))

    def write_start(self):
        self.r.setHeader('X-SVNPubSub-Version', '1')
        self.r.setHeader('content-type', 'application/vnd.apache.vc-notify+json')
        self.write('{"svnpubsub": {"version": 1}}\n\0')

    def write_heartbeat(self):
        self.write(json.dumps({"stillalive": time.time()}) + "\n\0")


class SvnPubSub(resource.Resource):
    isLeaf = True
    clients = []

    def cc(self):
        return len(self.clients)

    def remove(self, c):
        self.clients.remove(c)

    def render_GET(self, request):
        log.msg("REQUEST: %s"  % (request.uri))
        request.setHeader('content-type', 'text/plain')

        repository = None
        type = None

        uri = request.uri.split('/')
        uri_len = len(uri)
        if uri_len < 2 or uri_len > 4:
            request.setResponseCode(400)
            return "Invalid path\n"

        if uri_len >= 3:
          type = uri[2]

        if uri_len == 4:
          repository = uri[3]

        # Convert wild card to None.
        if type == '*':
          type = None
        if repository == '*':
          repository = None

        c = Client(self, request, type, repository)
        self.clients.append(c)
        c.start()
        return twisted.web.server.NOT_DONE_YET

    def notifyAll(self, commit):
        data = commit.render_commit()

        log.msg("COMMIT: %s (%d clients)" % (commit.render_log(), self.cc()))
        for client in self.clients:
            if client.interested_in(commit):
                client.write_data(data)



( run in 0.435 second using v1.01-cache-2.11-cpan-8644d7adfcd )