diff -r 215fd73cfe52 -r 0e8836be9541 mercurial/utils/storageutil.py --- a/mercurial/utils/storageutil.py Fri Sep 28 11:00:20 2018 -0700 +++ b/mercurial/utils/storageutil.py Fri Sep 28 11:03:17 2018 -0700 @@ -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'))