def _addrevision(self, node, text, transaction, link, p1, p2,
                     cachedelta, ifh, dfh):
        """internal function to add revisions to the log

        see addrevision for argument descriptions.
        invariants:
        - text is optional (can be None); if not set, cachedelta must be set.
          if both are set, they must correspond to eachother.
        """
        btext = [text]
        def buildtext():
            if btext[0] is not None:
                return btext[0]
            # flush any pending writes here so we can read it in revision
            if dfh:
                dfh.flush()
            ifh.flush()
            basetext = self.revision(self.node(cachedelta[0]))
            btext[0] = mdiff.patch(basetext, cachedelta[1])
            chk = hash(btext[0], p1, p2)
            if chk != node:
                raise RevlogError(_("consistency error in delta"))
            return btext[0]

        def builddelta(rev):
            # can we use the cached delta?
            if cachedelta and cachedelta[0] == rev:
                delta = cachedelta[1]
            else:
                t = buildtext()
                ptext = self.revision(self.node(rev))
                delta = mdiff.textdiff(ptext, t)
            data = compress(delta)
            l = len(data[1]) + len(data[0])
            if basecache[0] == rev:
                chainbase = basecache[1]
            else:
                chainbase = self.chainbase(rev)
            dist = l + offset - self.start(chainbase)
            if self._generaldelta:
                base = rev
            else:
                base = chainbase
            return dist, l, data, base, chainbase

        curr = len(self)
        prev = curr - 1
        base = chainbase = curr
        offset = self.end(prev)
        flags = 0
        d = None
        basecache = self._basecache
        p1r, p2r = self.rev(p1), self.rev(p2)

        # should we try to build a delta?
        if prev != nullrev:
            if self._generaldelta:
                if p1r >= basecache[1]:
                    d = builddelta(p1r)
                elif p2r >= basecache[1]:
                    d = builddelta(p2r)
                else:
                    d = builddelta(prev)
            else:
                d = builddelta(prev)
            dist, l, data, base, chainbase = d

        # full versions are inserted when the needed deltas
        # become comparable to the uncompressed text
        if text is None:
            textlen = mdiff.patchedsize(self.rawsize(cachedelta[0]),
                                        cachedelta[1])
        else:
            textlen = len(text)
        if d is None or dist > textlen * 2:
            text = buildtext()
            data = compress(text)
            l = len(data[1]) + len(data[0])
            base = chainbase = curr

        e = (offset_type(offset, flags), l, textlen,
             base, link, p1r, p2r, node)
        self.index.insert(-1, e)
        self.nodemap[node] = curr

        entry = self._io.packentry(e, self.node, self.version, curr)
        if not self._inline:
            transaction.add(self.datafile, offset)
            transaction.add(self.indexfile, curr * len(entry))
            if data[0]:
                dfh.write(data[0])
            dfh.write(data[1])
            dfh.flush()
            ifh.write(entry)
        else:
            offset += curr * self._io.size
            transaction.add(self.indexfile, offset, curr)
            ifh.write(entry)
            ifh.write(data[0])
            ifh.write(data[1])
            self.checkinlinesize(transaction, ifh)

        if type(text) == str: # only accept immutable objects
            self._cache = (node, curr, text)
        self._basecache = (curr, chainbase)
        return node