# HG changeset patch # User Gregory Szorc # Date 1538603849 25200 # Node ID f1a39128da95fa2abeca2aade650aca49c1dea55 # Parent 4a81d82474e9094d3b9d5f8d89743d4dc7da1291 filelog: add a hasnode() method (API) Missing in the file storage interface is the ability to query whether a specified value is a known node. This commit defines that interface member and implements it on the revlog and sqlite file stores. Storage unit tests have been added. The revlog implementation is a bit more complicated because index lookups don't consistently raise the same exception. For SQLite, we can simply look for a key in a dict. Differential Revision: https://phab.mercurial-scm.org/D5163 diff -r 4a81d82474e9 -r f1a39128da95 hgext/sqlitestore.py --- a/hgext/sqlitestore.py Sun Oct 21 22:26:00 2018 -0400 +++ b/hgext/sqlitestore.py Wed Oct 03 14:57:29 2018 -0700 @@ -381,6 +381,12 @@ def __iter__(self): return iter(pycompat.xrange(len(self._revisions))) + def hasnode(self, node): + if node == nullid: + return False + + return node in self._nodetorev + def revs(self, start=0, stop=None): return storageutil.iterrevs(len(self._revisions), start=start, stop=stop) diff -r 4a81d82474e9 -r f1a39128da95 mercurial/filelog.py --- a/mercurial/filelog.py Sun Oct 21 22:26:00 2018 -0400 +++ b/mercurial/filelog.py Wed Oct 03 14:57:29 2018 -0700 @@ -7,6 +7,10 @@ from __future__ import absolute_import +from .node import ( + nullid, + nullrev, +) from . import ( error, repository, @@ -33,6 +37,16 @@ def __iter__(self): return self._revlog.__iter__() + def hasnode(self, node): + if node in (nullid, nullrev): + return False + + try: + self._revlog.rev(node) + return True + except (TypeError, ValueError, IndexError, error.LookupError): + return False + def revs(self, start=0, stop=None): return self._revlog.revs(start=start, stop=stop) diff -r 4a81d82474e9 -r f1a39128da95 mercurial/repository.py --- a/mercurial/repository.py Sun Oct 21 22:26:00 2018 -0400 +++ b/mercurial/repository.py Wed Oct 03 14:57:29 2018 -0700 @@ -484,6 +484,16 @@ def __iter__(): """Iterate over revision numbers for this file.""" + def hasnode(node): + """Returns a bool indicating if a node is known to this store. + + Implementations must only return True for full, binary node values: + hex nodes, revision numbers, and partial node matches must be + rejected. + + The null node is never present. + """ + def revs(start=0, stop=None): """Iterate over revision numbers for this file, with control.""" diff -r 4a81d82474e9 -r f1a39128da95 mercurial/testing/storage.py --- a/mercurial/testing/storage.py Sun Oct 21 22:26:00 2018 -0400 +++ b/mercurial/testing/storage.py Wed Oct 03 14:57:29 2018 -0700 @@ -45,6 +45,13 @@ with self.assertRaises(StopIteration): next(gen) + self.assertFalse(f.hasnode(None)) + self.assertFalse(f.hasnode(0)) + self.assertFalse(f.hasnode(nullrev)) + self.assertFalse(f.hasnode(nullid)) + self.assertFalse(f.hasnode(b'0')) + self.assertFalse(f.hasnode(b'a' * 20)) + # revs() should evaluate to an empty list. self.assertEqual(list(f.revs()), []) @@ -161,6 +168,13 @@ with self.assertRaises(StopIteration): next(gen) + self.assertTrue(f.hasnode(node)) + self.assertFalse(f.hasnode(hex(node))) + self.assertFalse(f.hasnode(nullrev)) + self.assertFalse(f.hasnode(nullid)) + self.assertFalse(f.hasnode(node[0:12])) + self.assertFalse(f.hasnode(hex(node)[0:20])) + self.assertEqual(list(f.revs()), [0]) self.assertEqual(list(f.revs(start=1)), []) self.assertEqual(list(f.revs(start=0)), [0])