mercurial/utils/storageutil.py
changeset 40002 0e8836be9541
parent 39881 d63153611ed5
child 40003 ad8389ecd3f5
--- 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'))