diff --git a/tests/simplestorerepo.py b/tests/simplestorerepo.py --- a/tests/simplestorerepo.py +++ b/tests/simplestorerepo.py @@ -66,17 +66,24 @@ pass @interfaceutil.implementer(repository.irevisiondelta) -@attr.s(slots=True, frozen=True) +@attr.s(slots=True) class simplestorerevisiondelta(object): node = attr.ib() p1node = attr.ib() p2node = attr.ib() basenode = attr.ib() - linknode = attr.ib() flags = attr.ib() baserevisionsize = attr.ib() revision = attr.ib() delta = attr.ib() + linknode = attr.ib(default=None) + +@interfaceutil.implementer(repository.iverifyproblem) +@attr.s(frozen=True) +class simplefilestoreproblem(object): + warning = attr.ib(default=None) + error = attr.ib(default=None) + node = attr.ib(default=None) @interfaceutil.implementer(repository.ifilestorage) class filestorage(object): @@ -192,6 +199,13 @@ return self._indexbyrev[rev][b'node'] + def hasnode(self, node): + validatenode(node) + return node in self._indexbynode + + def censorrevision(self, tr, censornode, tombstone=b''): + raise NotImplementedError('TODO') + def lookup(self, node): if isinstance(node, int): return self.node(node) @@ -290,7 +304,11 @@ raise simplestoreerror(_("integrity check failed on %s") % self._path) - def revision(self, node, raw=False): + def revision(self, nodeorrev, raw=False): + if isinstance(nodeorrev, int): + node = self.node(nodeorrev) + else: + node = nodeorrev validatenode(node) if node == nullid: @@ -409,6 +427,44 @@ return [b'/'.join((self._storepath, f)) for f in entries] + def storageinfo(self, exclusivefiles=False, sharedfiles=False, + revisionscount=False, trackedsize=False, + storedsize=False): + # TODO do a real implementation of this + return { + 'exclusivefiles': [], + 'sharedfiles': [], + 'revisionscount': len(self), + 'trackedsize': 0, + 'storedsize': None, + } + + def verifyintegrity(self, state): + state['skipread'] = set() + for rev in self: + node = self.node(rev) + try: + self.revision(node) + except Exception as e: + yield simplefilestoreproblem( + error='unpacking %s: %s' % (node, e), + node=node) + state['skipread'].add(node) + + def emitrevisions(self, nodes, nodesorder=None, revisiondata=False, + assumehaveparentrevisions=False, + deltamode=repository.CG_DELTAMODE_STD): + # TODO this will probably break on some ordering options. + nodes = [n for n in nodes if n != nullid] + if not nodes: + return + for delta in storageutil.emitrevisions( + self, nodes, nodesorder, simplestorerevisiondelta, + revisiondata=revisiondata, + assumehaveparentrevisions=assumehaveparentrevisions, + deltamode=deltamode): + yield delta + def add(self, text, meta, transaction, linkrev, p1, p2): if meta or text.startswith(b'\1\n'): text = storageutil.packmeta(meta, text) @@ -489,15 +545,26 @@ if addrevisioncb: addrevisioncb(self, node) + return nodes - return nodes + def _headrevs(self): + # Assume all revisions are heads by default. + revishead = {rev: True for rev in self._indexbyrev} + + for rev, entry in self._indexbyrev.items(): + # Unset head flag for all seen parents. + revishead[self.rev(entry[b'p1'])] = False + revishead[self.rev(entry[b'p2'])] = False + + return [rev for rev, ishead in sorted(revishead.items()) + if ishead] def heads(self, start=None, stop=None): # This is copied from revlog.py. if start is None and stop is None: if not len(self): return [nullid] - return [self.node(r) for r in self.headrevs()] + return [self.node(r) for r in self._headrevs()] if start is None: start = nullid @@ -537,41 +604,9 @@ return c def getstrippoint(self, minlink): - - # This is largely a copy of revlog.getstrippoint(). - brokenrevs = set() - strippoint = len(self) - - heads = {} - futurelargelinkrevs = set() - for head in self.heads(): - headlinkrev = self.linkrev(self.rev(head)) - heads[head] = headlinkrev - if headlinkrev >= minlink: - futurelargelinkrevs.add(headlinkrev) - - # This algorithm involves walking down the rev graph, starting at the - # heads. Since the revs are topologically sorted according to linkrev, - # once all head linkrevs are below the minlink, we know there are - # no more revs that could have a linkrev greater than minlink. - # So we can stop walking. - while futurelargelinkrevs: - strippoint -= 1 - linkrev = heads.pop(strippoint) - - if linkrev < minlink: - brokenrevs.add(strippoint) - else: - futurelargelinkrevs.remove(linkrev) - - for p in self.parentrevs(strippoint): - if p != nullrev: - plinkrev = self.linkrev(p) - heads[p] = plinkrev - if plinkrev >= minlink: - futurelargelinkrevs.add(plinkrev) - - return strippoint, brokenrevs + return storageutil.resolvestripinfo( + minlink, len(self) - 1, self._headrevs(), self.linkrev, + self.parentrevs) def strip(self, minlink, transaction): if not len(self): @@ -631,9 +666,9 @@ def featuresetup(ui, supported): supported.add(REQUIREMENT) -def newreporequirements(orig, ui): +def newreporequirements(orig, ui, createopts): """Modifies default requirements for new repos to use the simple store.""" - requirements = orig(ui) + requirements = orig(ui, createopts) # These requirements are only used to affect creation of the store # object. We have our own store. So we can remove them. @@ -665,5 +700,5 @@ extensions.wrapfunction(localrepo, 'newreporequirements', newreporequirements) - extensions.wrapfunction(store, 'store', makestore) + extensions.wrapfunction(localrepo, 'makestore', makestore) extensions.wrapfunction(verify.verifier, '__init__', verifierinit)