diff --git a/mercurial/filelog.py b/mercurial/filelog.py --- a/mercurial/filelog.py +++ b/mercurial/filelog.py @@ -49,7 +49,8 @@ return self._revlog.node(rev) def lookup(self, node): - return self._revlog.lookup(node) + return storageutil.fileidlookup(self._revlog, node, + self._revlog.indexfile) def linkrev(self, rev): return self._revlog.linkrev(rev) diff --git a/mercurial/repository.py b/mercurial/repository.py --- a/mercurial/repository.py +++ b/mercurial/repository.py @@ -1099,9 +1099,6 @@ that can be converted to an integer. Raises ``error.LookupError`` if a ndoe could not be resolved. - - TODO this is only used by debug* commands and can probably be deleted - easily. """ def parents(node): diff --git a/mercurial/testing/storage.py b/mercurial/testing/storage.py --- a/mercurial/testing/storage.py +++ b/mercurial/testing/storage.py @@ -85,21 +85,19 @@ self.assertEqual(f.lookup(nullid), nullid) self.assertEqual(f.lookup(nullrev), nullid) self.assertEqual(f.lookup(hex(nullid)), nullid) - - # String converted to integer doesn't work for nullrev. - with self.assertRaises(error.LookupError): - f.lookup(b'%d' % nullrev) + self.assertEqual(f.lookup(b'%d' % nullrev), nullid) with self.assertRaises(error.LookupError): f.lookup(b'badvalue') - self.assertEqual(f.lookup(hex(nullid)[0:12]), nullid) + with self.assertRaises(error.LookupError): + f.lookup(hex(nullid)[0:12]) with self.assertRaises(error.LookupError): f.lookup(b'-2') - # TODO this is wonky. - self.assertEqual(f.lookup(b'0'), nullid) + with self.assertRaises(error.LookupError): + f.lookup(b'0') with self.assertRaises(error.LookupError): f.lookup(b'1') @@ -197,7 +195,9 @@ self.assertEqual(f.lookup(-1), nullid) self.assertEqual(f.lookup(b'0'), node) self.assertEqual(f.lookup(hex(node)), node) - self.assertEqual(f.lookup(hex(node)[0:12]), node) + + with self.assertRaises(error.LookupError): + f.lookup(hex(node)[0:12]) with self.assertRaises(IndexError): f.lookup(-2) diff --git a/mercurial/utils/storageutil.py b/mercurial/utils/storageutil.py --- a/mercurial/utils/storageutil.py +++ b/mercurial/utils/storageutil.py @@ -10,10 +10,13 @@ import hashlib import re +from ..i18n import _ from ..node import ( + bin, nullid, ) from .. import ( + error, pycompat, ) @@ -99,3 +102,53 @@ stop = storelen return pycompat.xrange(start, stop, step) + +def fileidlookup(store, fileid, identifier): + """Resolve the file node for a value. + + ``store`` is an object implementing the ``ifileindex`` interface. + + ``fileid`` can be: + + * A 20 byte binary node. + * An integer revision number + * A 40 byte hex node. + * A bytes that can be parsed as an integer representing a revision number. + + ``identifier`` is used to populate ``error.LookupError`` with an identifier + for the store. + + Raises ``error.LookupError`` on failure. + """ + if isinstance(fileid, int): + return store.node(fileid) + + if len(fileid) == 20: + try: + store.rev(fileid) + return fileid + except error.LookupError: + pass + + if len(fileid) == 40: + try: + rawnode = bin(fileid) + store.rev(rawnode) + return rawnode + except TypeError: + pass + + try: + rev = int(fileid) + + if b'%d' % rev != fileid: + raise ValueError + + try: + return store.node(rev) + except (IndexError, TypeError): + pass + except (ValueError, OverflowError): + pass + + raise error.LookupError(fileid, identifier, _('no match found'))