D5519: simplestorerepo: minimal changes required to get this mostly working again

durin42 (Augie Fackler) phabricator at mercurial-scm.org
Mon Jan 7 23:49:12 UTC 2019


durin42 created this revision.
durin42 added a reviewer: indygreg.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  I was going to change this code's use of CBOR to use our in-house CBOR code,
  but discovered it's been broken for a while. This messy change gets it back to
  a point where it mostly works, I think roughly as well as it ever did.
  
  Should we keep this and fix it up the rest of the way, or dump it in favor of
  the sqlite store? Would this be a good jumping-off point for some sort of
  union store that could facilitate a cleanup in remotefilelog?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5519

AFFECTED FILES
  tests/simplestorerepo.py

CHANGE DETAILS

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)
- at attr.s(slots=True, frozen=True)
+ at 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)
+
+ at interfaceutil.implementer(repository.iverifyproblem)
+ at 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)



To: durin42, indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list