hgext/sqlitestore.py
changeset 47012 d55b71393907
parent 46780 6266d19556ad
child 47077 119790e1c67c
equal deleted inserted replaced
46992:5fa019ceb499 47012:d55b71393907
    50 import threading
    50 import threading
    51 import zlib
    51 import zlib
    52 
    52 
    53 from mercurial.i18n import _
    53 from mercurial.i18n import _
    54 from mercurial.node import (
    54 from mercurial.node import (
    55     nullid,
       
    56     nullrev,
    55     nullrev,
    57     sha1nodeconstants,
    56     sha1nodeconstants,
    58     short,
    57     short,
    59 )
    58 )
    60 from mercurial.thirdparty import attr
    59 from mercurial.thirdparty import attr
   364                 raise SQLiteStoreError(
   363                 raise SQLiteStoreError(
   365                     _(b'sqlite database has inconsistent revision numbers')
   364                     _(b'sqlite database has inconsistent revision numbers')
   366                 )
   365                 )
   367 
   366 
   368             if p1rev == nullrev:
   367             if p1rev == nullrev:
   369                 p1node = nullid
   368                 p1node = sha1nodeconstants.nullid
   370             else:
   369             else:
   371                 p1node = self._revtonode[p1rev]
   370                 p1node = self._revtonode[p1rev]
   372 
   371 
   373             if p2rev == nullrev:
   372             if p2rev == nullrev:
   374                 p2node = nullid
   373                 p2node = sha1nodeconstants.nullid
   375             else:
   374             else:
   376                 p2node = self._revtonode[p2rev]
   375                 p2node = self._revtonode[p2rev]
   377 
   376 
   378             entry = revisionentry(
   377             entry = revisionentry(
   379                 rid=rid,
   378                 rid=rid,
   398 
   397 
   399     def __iter__(self):
   398     def __iter__(self):
   400         return iter(pycompat.xrange(len(self._revisions)))
   399         return iter(pycompat.xrange(len(self._revisions)))
   401 
   400 
   402     def hasnode(self, node):
   401     def hasnode(self, node):
   403         if node == nullid:
   402         if node == sha1nodeconstants.nullid:
   404             return False
   403             return False
   405 
   404 
   406         return node in self._nodetorev
   405         return node in self._nodetorev
   407 
   406 
   408     def revs(self, start=0, stop=None):
   407     def revs(self, start=0, stop=None):
   409         return storageutil.iterrevs(
   408         return storageutil.iterrevs(
   410             len(self._revisions), start=start, stop=stop
   409             len(self._revisions), start=start, stop=stop
   411         )
   410         )
   412 
   411 
   413     def parents(self, node):
   412     def parents(self, node):
   414         if node == nullid:
   413         if node == sha1nodeconstants.nullid:
   415             return nullid, nullid
   414             return sha1nodeconstants.nullid, sha1nodeconstants.nullid
   416 
   415 
   417         if node not in self._revisions:
   416         if node not in self._revisions:
   418             raise error.LookupError(node, self._path, _(b'no node'))
   417             raise error.LookupError(node, self._path, _(b'no node'))
   419 
   418 
   420         entry = self._revisions[node]
   419         entry = self._revisions[node]
   429 
   428 
   430         entry = self._revisions[self._revtonode[rev]]
   429         entry = self._revisions[self._revtonode[rev]]
   431         return entry.p1rev, entry.p2rev
   430         return entry.p1rev, entry.p2rev
   432 
   431 
   433     def rev(self, node):
   432     def rev(self, node):
   434         if node == nullid:
   433         if node == sha1nodeconstants.nullid:
   435             return nullrev
   434             return nullrev
   436 
   435 
   437         if node not in self._nodetorev:
   436         if node not in self._nodetorev:
   438             raise error.LookupError(node, self._path, _(b'no node'))
   437             raise error.LookupError(node, self._path, _(b'no node'))
   439 
   438 
   440         return self._nodetorev[node]
   439         return self._nodetorev[node]
   441 
   440 
   442     def node(self, rev):
   441     def node(self, rev):
   443         if rev == nullrev:
   442         if rev == nullrev:
   444             return nullid
   443             return sha1nodeconstants.nullid
   445 
   444 
   446         if rev not in self._revtonode:
   445         if rev not in self._revtonode:
   447             raise IndexError(rev)
   446             raise IndexError(rev)
   448 
   447 
   449         return self._revtonode[rev]
   448         return self._revtonode[rev]
   483         return dagop.descendantrevs(revs, self.revs, self.parentrevs)
   482         return dagop.descendantrevs(revs, self.revs, self.parentrevs)
   484 
   483 
   485     def heads(self, start=None, stop=None):
   484     def heads(self, start=None, stop=None):
   486         if start is None and stop is None:
   485         if start is None and stop is None:
   487             if not len(self):
   486             if not len(self):
   488                 return [nullid]
   487                 return [sha1nodeconstants.nullid]
   489 
   488 
   490         startrev = self.rev(start) if start is not None else nullrev
   489         startrev = self.rev(start) if start is not None else nullrev
   491         stoprevs = {self.rev(n) for n in stop or []}
   490         stoprevs = {self.rev(n) for n in stop or []}
   492 
   491 
   493         revs = dagop.headrevssubset(
   492         revs = dagop.headrevssubset(
   527             return len(self.read(node))
   526             return len(self.read(node))
   528 
   527 
   529         return len(self.revision(node))
   528         return len(self.revision(node))
   530 
   529 
   531     def revision(self, node, raw=False, _verifyhash=True):
   530     def revision(self, node, raw=False, _verifyhash=True):
   532         if node in (nullid, nullrev):
   531         if node in (sha1nodeconstants.nullid, nullrev):
   533             return b''
   532             return b''
   534 
   533 
   535         if isinstance(node, int):
   534         if isinstance(node, int):
   536             node = self.node(node)
   535             node = self.node(node)
   537 
   536 
   594         if nodesorder not in (b'nodes', b'storage', b'linear', None):
   593         if nodesorder not in (b'nodes', b'storage', b'linear', None):
   595             raise error.ProgrammingError(
   594             raise error.ProgrammingError(
   596                 b'unhandled value for nodesorder: %s' % nodesorder
   595                 b'unhandled value for nodesorder: %s' % nodesorder
   597             )
   596             )
   598 
   597 
   599         nodes = [n for n in nodes if n != nullid]
   598         nodes = [n for n in nodes if n != sha1nodeconstants.nullid]
   600 
   599 
   601         if not nodes:
   600         if not nodes:
   602             return
   601             return
   603 
   602 
   604         # TODO perform in a single query.
   603         # TODO perform in a single query.
   703 
   702 
   704             if wireflags & ~repository.REVISION_FLAG_CENSORED:
   703             if wireflags & ~repository.REVISION_FLAG_CENSORED:
   705                 raise SQLiteStoreError(b'unhandled revision flag')
   704                 raise SQLiteStoreError(b'unhandled revision flag')
   706 
   705 
   707             if maybemissingparents:
   706             if maybemissingparents:
   708                 if p1 != nullid and not self.hasnode(p1):
   707                 if p1 != sha1nodeconstants.nullid and not self.hasnode(p1):
   709                     p1 = nullid
   708                     p1 = sha1nodeconstants.nullid
   710                     storeflags |= FLAG_MISSING_P1
   709                     storeflags |= FLAG_MISSING_P1
   711 
   710 
   712                 if p2 != nullid and not self.hasnode(p2):
   711                 if p2 != sha1nodeconstants.nullid and not self.hasnode(p2):
   713                     p2 = nullid
   712                     p2 = sha1nodeconstants.nullid
   714                     storeflags |= FLAG_MISSING_P2
   713                     storeflags |= FLAG_MISSING_P2
   715 
   714 
   716             baserev = self.rev(deltabase)
   715             baserev = self.rev(deltabase)
   717 
   716 
   718             # If base is censored, delta must be full replacement in a single
   717             # If base is censored, delta must be full replacement in a single
   734 
   733 
   735             if node in self._revisions:
   734             if node in self._revisions:
   736                 # Possibly reset parents to make them proper.
   735                 # Possibly reset parents to make them proper.
   737                 entry = self._revisions[node]
   736                 entry = self._revisions[node]
   738 
   737 
   739                 if entry.flags & FLAG_MISSING_P1 and p1 != nullid:
   738                 if (
       
   739                     entry.flags & FLAG_MISSING_P1
       
   740                     and p1 != sha1nodeconstants.nullid
       
   741                 ):
   740                     entry.p1node = p1
   742                     entry.p1node = p1
   741                     entry.p1rev = self._nodetorev[p1]
   743                     entry.p1rev = self._nodetorev[p1]
   742                     entry.flags &= ~FLAG_MISSING_P1
   744                     entry.flags &= ~FLAG_MISSING_P1
   743 
   745 
   744                     self._db.execute(
   746                     self._db.execute(
   745                         'UPDATE fileindex SET p1rev=?, flags=? WHERE id=?',
   747                         'UPDATE fileindex SET p1rev=?, flags=? WHERE id=?',
   746                         (self._nodetorev[p1], entry.flags, entry.rid),
   748                         (self._nodetorev[p1], entry.flags, entry.rid),
   747                     )
   749                     )
   748 
   750 
   749                 if entry.flags & FLAG_MISSING_P2 and p2 != nullid:
   751                 if (
       
   752                     entry.flags & FLAG_MISSING_P2
       
   753                     and p2 != sha1nodeconstants.nullid
       
   754                 ):
   750                     entry.p2node = p2
   755                     entry.p2node = p2
   751                     entry.p2rev = self._nodetorev[p2]
   756                     entry.p2rev = self._nodetorev[p2]
   752                     entry.flags &= ~FLAG_MISSING_P2
   757                     entry.flags &= ~FLAG_MISSING_P2
   753 
   758 
   754                     self._db.execute(
   759                     self._db.execute(
   759                 if duplicaterevisioncb:
   764                 if duplicaterevisioncb:
   760                     duplicaterevisioncb(self, self.rev(node))
   765                     duplicaterevisioncb(self, self.rev(node))
   761                 empty = False
   766                 empty = False
   762                 continue
   767                 continue
   763 
   768 
   764             if deltabase == nullid:
   769             if deltabase == sha1nodeconstants.nullid:
   765                 text = mdiff.patch(b'', delta)
   770                 text = mdiff.patch(b'', delta)
   766                 storedelta = None
   771                 storedelta = None
   767             else:
   772             else:
   768                 text = None
   773                 text = None
   769                 storedelta = (deltabase, delta)
   774                 storedelta = (deltabase, delta)
  1010 
  1015 
  1011         else:
  1016         else:
  1012             assert revisiondata is not None
  1017             assert revisiondata is not None
  1013             deltabase = p1
  1018             deltabase = p1
  1014 
  1019 
  1015             if deltabase == nullid:
  1020             if deltabase == sha1nodeconstants.nullid:
  1016                 delta = revisiondata
  1021                 delta = revisiondata
  1017             else:
  1022             else:
  1018                 delta = mdiff.textdiff(
  1023                 delta = mdiff.textdiff(
  1019                     self.revision(self.rev(deltabase)), revisiondata
  1024                     self.revision(self.rev(deltabase)), revisiondata
  1020                 )
  1025                 )
  1021 
  1026 
  1022         # File index stores a pointer to its delta and the parent delta.
  1027         # File index stores a pointer to its delta and the parent delta.
  1023         # The parent delta is stored via a pointer to the fileindex PK.
  1028         # The parent delta is stored via a pointer to the fileindex PK.
  1024         if deltabase == nullid:
  1029         if deltabase == sha1nodeconstants.nullid:
  1025             baseid = None
  1030             baseid = None
  1026         else:
  1031         else:
  1027             baseid = self._revisions[deltabase].rid
  1032             baseid = self._revisions[deltabase].rid
  1028 
  1033 
  1029         # Deltas are stored with a hash of their content. This allows
  1034         # Deltas are stored with a hash of their content. This allows
  1053 
  1058 
  1054         deltaid = insertdelta(self._db, compression, deltahash, deltablob)
  1059         deltaid = insertdelta(self._db, compression, deltahash, deltablob)
  1055 
  1060 
  1056         rev = len(self)
  1061         rev = len(self)
  1057 
  1062 
  1058         if p1 == nullid:
  1063         if p1 == sha1nodeconstants.nullid:
  1059             p1rev = nullrev
  1064             p1rev = nullrev
  1060         else:
  1065         else:
  1061             p1rev = self._nodetorev[p1]
  1066             p1rev = self._nodetorev[p1]
  1062 
  1067 
  1063         if p2 == nullid:
  1068         if p2 == sha1nodeconstants.nullid:
  1064             p2rev = nullrev
  1069             p2rev = nullrev
  1065         else:
  1070         else:
  1066             p2rev = self._nodetorev[p2]
  1071             p2rev = self._nodetorev[p2]
  1067 
  1072 
  1068         rid = self._db.execute(
  1073         rid = self._db.execute(